J'utilise Python 2.5.
Voici mon arborescence de dossiers:
ptdraft/
nib.py
simulations/
life/
life.py
(J'ai également __init__.py
dans chaque dossier, omis ici pour plus de lisibilité)
Comment importer le nib
module depuis l'intérieur du life
module? J'espère qu'il est possible de le faire sans bricoler avec sys.path.
Remarque: Le module principal en cours d'exécution se trouve dans le ptdraft
dossier.
__init__.py
. S.Lott: Je ne sais pas comment vérifier ...sys.path
ouPYTHONPATH
réponses et vérifier excellente réponse de NP8 . Oui, c'est une longue lecture. Oui, cela ressemble à beaucoup de travail. Mais c'est la seule réponse qui résout le problème correctement et proprement.Réponses:
Il semble que le problème ne soit pas lié au fait que le module se trouve dans un répertoire parent ou quelque chose comme ça.
Vous devez ajouter le répertoire contenant
ptdraft
PYTHONPATHVous avez dit que cela
import nib
fonctionnait avec vous, cela signifie probablement que vous vous êtes ajoutéptdraft
(pas son parent) à PYTHONPATH.la source
import sys
et ensuitesys.path.append("..\<parent_folder>")
Vous pouvez utiliser des importations relatives (python> = 2.5):
(Quoi de neuf dans Python 2.5) PEP 328: Importations absolues et relatives
EDIT : ajouté un autre point '.' monter deux packages
la source
ValueError: Attempted relative import in non-package
__init__.py
fichier.__init__.py
n'est pas la seule chose que vous devez faire: stackoverflow.com/questions/11536764/…Les importations relatives (comme dans
from .. import mymodule
) ne fonctionnent que dans un package. Pour importer 'mymodule' qui se trouve dans le répertoire parent de votre module actuel:edit : l'
__file__
attribut n'est pas toujours donné. Au lieu d'utiliser,os.path.abspath(__file__)
j'ai maintenant suggéré d'utiliser le module d'inspection pour récupérer le nom de fichier (et le chemin) du fichier actuella source
sys.path.insert(1, os.path.join(sys.path[0], '..'))
parentdir
, mais dans l'un des chemins déjà spécifiés danssys.path
, il y a un autre module avec le nom 'mymodule'. L'insertion deparentdir
as comme premier élément de lasys.path
liste garantit que le module deparentdir
sera importé à la place.sys.path.insert(1, os.path.realpath(os.path.pardir))
fonctionne aussi.J'ai également publié une réponse similaire à la question concernant les importations à partir de paquets frères. Vous pouvez le voir ici .
Solution sans
sys.path
hacksSommaire
packaged_stuff
)setup.py
script de création dans lequel vous utilisez setuptools.setup () .pip install -e <myproject_folder>
from packaged_stuff.modulename import function_name
Installer
Je suppose que la même structure de dossiers que dans la question
J'appelle le
.
dossier racine, et dans mon cas, il se trouve dansC:\tmp\test_imports
.Pas
1) Ajoutez un
setup.py
au dossier racineLe contenu de la
setup.py
peut être simplementFondamentalement, «tout»
setup.py
fonctionnerait. Ceci est juste un exemple de travail minimal.2) Utilisez un environnement virtuel
Si vous connaissez les environnements virtuels, activez-en un et passez à l'étape suivante. L'utilisation d'environnements virtuels n'est pas absolument requise, mais ils vous aideront vraiment à long terme (lorsque vous avez plus d'un projet en cours ..). Les étapes les plus élémentaires sont (exécutées dans le dossier racine)
python -m venv venv
. /venv/bin/activate
(Linux) ou./venv/Scripts/activate
(Win)Pour en savoir plus à ce sujet, il suffit de Google sur "tutoriel python virtualenv" ou similaire. Vous n'avez probablement jamais besoin d'autres commandes que la création, l'activation et la désactivation.
Une fois que vous avez créé et activé un environnement virtuel, votre console doit donner le nom de l'environnement virtuel entre parenthèses
3) Pip installez votre projet dans un état modifiable
Installez votre package de niveau supérieur à l'
myproject
aide depip
. L'astuce consiste à utiliser l'-e
indicateur lors de l'installation. De cette façon, il est installé dans un état modifiable et toutes les modifications apportées aux fichiers .py seront automatiquement incluses dans le package installé.Dans le répertoire racine, exécutez
pip install -e .
(notez le point, il signifie "répertoire courant")Vous pouvez également voir qu'il est installé à l'aide de
pip freeze
4) Importer en ajoutant
mainfolder
à chaque importationDans cet exemple, le
mainfolder
seraitptdraft
. Cela présente l'avantage que vous ne rencontrerez pas de collisions de noms avec d'autres noms de module (à partir de la bibliothèque standard python ou de modules tiers).Exemple d'utilisation
nib.py
life.py
Running life.py
la source
sys.path
et où le code serait généralement installé par les utilisateurs finaux. C'est mieux que lessys.path
hacks (et vous pouvez inclure l'utilisation de PYTHONPATH dans cette catégorie de hacks de chemin) car cela signifie que le code en développement devrait se comporter de la même manière pour vous que pour les autres utilisateurs. En revanche, lors de l'utilisation de modifications de chemin, les instructions d'importation seraient résolues d'une manière différente.Vous pouvez utiliser le chemin d'accès dépendant du système d'exploitation dans le "chemin de recherche de module" qui est répertorié dans sys.path . Ainsi, vous pouvez facilement ajouter un répertoire parent comme suit
Si vous souhaitez ajouter un répertoire parent-parent,
Cela fonctionne à la fois en python 2 et 3.
la source
Si l'ajout de votre dossier de modules au PYTHONPATH n'a pas fonctionné, vous pouvez modifier la liste sys.path dans votre programme où l'interpréteur Python recherche les modules à importer, la documentation de python indique:
Sachant cela, vous pouvez effectuer les opérations suivantes dans votre programme:
la source
/path/to/ptdraft
faudrait le modifier. Il existe des solutions qui élaborent le répertoire actuel du fichier et l'importent également à partir du dossier parent.Je ne sais pas grand-chose sur python 2.
En python 3, le dossier parent peut être ajouté comme suit:
... et puis on peut en importer des modules
la source
'..'
mène au répertoire avec le module en question.Voici une réponse simple pour que vous puissiez voir comment cela fonctionne, petit et multiplateforme.
Il n'utilise que des modules intégrés (
os
,sys
etinspect
) et devrait donc fonctionnersur n'importe quel système d'exploitation (OS) car Python est conçu pour cela.
Code de réponse plus court - moins de lignes et de variables
Pour moins de lignes que cela, remplacez la deuxième ligne par
import os.path as path, sys, inspect
,ajoutez
inspect.
au début degetsourcefile
(ligne 3) et supprimez la première ligne.- cependant, cela importe tout le module et pourrait donc nécessiter plus de temps, de mémoire et de ressources.
Le code de ma réponse ( version longue )
Il utilise un exemple d'une réponse Stack Overflow Comment puis-je obtenir le chemin du
fichier en cours d' exécution en Python? pour trouver la source (nom de fichier) du code en cours d'exécution avec un outil intégré.
Mon code ajoute un chemin de fichier à
sys.path
, la liste des chemins de pythoncar cela permet à Python d'importer des modules de ce dossier.
Après avoir importé un module dans le code, c'est une bonne idée de s'exécuter
sys.path.pop(0)
sur une nouvelle lignelorsque ce dossier ajouté a un module portant le même nom qu'un autre module importé
plus tard dans le programme. Vous devez supprimer l'élément de liste ajouté avant l'importation, pas les autres chemins.
Si votre programme n'importe pas d'autres modules, il est prudent de ne pas supprimer le chemin du fichier car
après la fin d'un programme (ou le redémarrage du shell Python), toutes les modifications apportées
sys.path
disparaissent.Remarques sur une variable de nom de fichier
Ma réponse n'utilise pas la
__file__
variable pour obtenir le chemin d'accès / nom de fichier ducode en cours d'exécution car les utilisateurs ici l'ont souvent décrit comme peu fiable . Vous ne devez pas l'utiliser
pour importer des modules du dossier parent dans des programmes utilisés par d'autres personnes.
Quelques exemples où cela ne fonctionne pas (citation de cette question Stack Overflow):
• il ne peut pas être trouvé sur certaines plates-formes • ce n'est parfois pas le chemin complet du fichier
la source
sys.path.pop(0)
immédiatement après avoir importé le module souhaité. Cependant, les importations ultérieures sont toujours allées à cet endroit. Par exemple, j'aiapp/config
,app/tools
etapp/submodule/config
. Desubmodule
, j'insèreapp/
pour importertools
, puis supprimeapp/
et essaie d'importerconfig
, mais j'obtiens à laapp/config
place deapp/submodule/config
.tools
importations importait également du répertoireconfig
parent. Donc, quand j'ai essayé de faire plus tard à l'sys.path.pop(0); import config
intérieursubmodule
, en espérant obtenirapp/submodule/config
, j'obtenais réellementapp/config
. De toute évidence, Python renvoie une version en cache d'un module portant le même nom au lieu de vérifier réellement la présencesys.path
d'un module correspondant à ce nom.sys.path
dans ce cas était modifié correctement, Python ne le vérifiait tout simplement pas car le module portant le même nom avait déjà été chargé.sys.modules
... sys.modules est accessible en écriture. La suppression d'une clé invalidera l'entrée de cache pour le module nommé, obligeant Python à effectuer une nouvelle recherche lors de sa prochaine importation. ... Attention cependant, comme si vous gardiez une référence à l'objet module, invalidiez son cache puis réimportiez, les deux objets seront différents. En revanche,importlib.reload()
va réutiliser et réinitialiser le contenu du module ...os.path.realpath(getsourcefile(lambda:0) + "/../..")
. Obtiendra le fichier source actuel ajouté avec deux symboles de répertoire parent. Je n'ai pas utiliséos.path.sep
comme celagetsourcefile
renvoie une chaîne utilisant/
même sous Windows.realpath
prendra soin de faire sauter deux entrées de répertoire à partir du chemin complet (dans ce cas, le nom de fichier, puis le répertoire actuel) qui donne le répertoire parent.Voici une solution plus générique qui inclut le répertoire parent dans sys.path (fonctionne pour moi):
la source
import os, sys\n sys.path.insert(0,os.path.pardir)
même chose, mais sorther :) (pas de ligne dans les commentaires)os.path.pardir
vous n'obtiendrez pas le chemin réel du parent, juste le chemin relatif d'où vous appelez lesys.path.insert()
__file__
variable qui peut être peu fiable (n'est pas toujours le chemin d'accès complet au fichier, ne fonctionne pas sur tous les systèmes d'exploitation, etc.) comme les utilisateurs de StackOverflow l'ont souvent mentionné. Changer la réponse pour ne pas l'inclure causera moins de problèmes et sera plus compatible avec les autres. Pour plus d'informations, voir stackoverflow.com/a/33532002/3787376 .J'ai trouvé que la méthode suivante fonctionne pour importer un package à partir du répertoire parent du script. Dans l'exemple, je voudrais importer des fonctions
env.py
depuis leapp.db
package.la source
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path
est généralement une mauvaise idée. Vous avez besoin d'un moyen ( par exemple ,PYTHONPATH
) pour que votre bibliothèque soit accessible à un autre code (ou bien ce n'est pas vraiment une bibliothèque); utilisez-le tout le temps!Les solutions mentionnées ci-dessus conviennent également. Une autre solution à ce problème est
Si vous souhaitez importer quoi que ce soit à partir du répertoire de niveau supérieur. Alors,
En outre, si vous souhaitez importer un module du répertoire parent. Alors,
En outre, si vous souhaitez importer un module du répertoire parent. Alors,
De cette façon, vous pouvez importer n'importe quelle méthode particulière si vous le souhaitez.
la source
sys.path.append
hacks ci-dessus et je ne peux pas importer ma bibliothèque comme ça. C'est ce que j'ai essayé de faire avant de commencer sur Google :) Ok, c'était çaValueError: attempted relative import beyond top-level package
Pour moi, le plus court et mon oneliner préféré pour accéder au répertoire parent est:
ou:
os.getcwd () renvoie le nom du répertoire de travail en cours, os.path.dirname (nom_répertoire) renvoie le nom du répertoire de celui qui a été transmis.
En fait, à mon avis, l'architecture de projet Python devrait être effectuée de la manière où aucun module du répertoire enfant n'utilisera de module du répertoire parent. Si quelque chose comme cela se produit, il vaut la peine de repenser l'arborescence du projet.
Une autre façon consiste à ajouter le répertoire parent à la variable d'environnement système PYTHONPATH.
la source
Dans un cahier Jupyter
Tant que vous travaillez dans un bloc-notes Jupyter, cette courte solution peut être utile:
Cela fonctionne même sans
__init__.py
fichier.Je l'ai testé avec Anaconda3 sur Linux et Windows 7.
la source
%cd -
après l'importation, de sorte que le répertoire actuel du bloc-notes reste inchangé.import sys sys.path.append('../')
la source
Lorsqu'elle n'est pas dans un environnement de package avec des
__init__.py
fichiers, la bibliothèque pathlib (incluse avec> = Python 3.4) rend très concis et intuitif l'ajout du chemin du répertoire parent au PYTHONPATH:la source
même style que la réponse précédente - mais en moins de lignes: P
le fichier renvoie l'emplacement dans lequel vous travaillez
la source
Travaillez avec les bibliothèques. Créez une bibliothèque appelée nib, installez-la à l'aide de setup.py, laissez-la résider dans des packages de site et vos problèmes sont résolus. Vous n'avez pas à fourrer tout ce que vous faites dans un seul paquet. Brisez-le en morceaux.
la source
site-packages
chaque fois qu'ils l'exécutent sur un ordinateur différent.Dans un système Linux, vous pouvez créer un lien logiciel du dossier "life" vers le fichier nib.py. Ensuite, vous pouvez simplement l'importer comme:
la source