L'importation de modules dossier parent
Je suis en cours d'exécution Python 2.5.
C'est mon arborescence de dossiers:
ptdraft/
nib.py
simulations/
life/
life.py
(J'ai aussi __init__.py
dans chaque dossier, omis ici pour des raisons de lisibilité)
Comment puis-je importer les nib
module à partir de l'intérieur de la life
module? J'espère que c'est possible de le faire sans bricoler avec sys.chemin d'accès.
Remarque: Le module principal en cours d'exécution est dans le ptdraft
dossier.
- Quel est votre PYTHONPATH paramètre?
- Ross: j'ai regardé là. Que dois-je faire à ce sujet? J'ai déjà un
__init__.py
. S. Lott: je ne sais pas comment faire pour vérifier... - echo $PYTHONPATH de la coquille; import sys; print sys.chemin d'accès de l'intérieur de Python. docs.python.org/tutorial/...
- Google est un bouillonné de moteur de recherche, de sorte que le fait que ce résultat est assez élevé pour vous n'a pas d'importance. Le plus important est le fait que la non-barboter moteur de recherche DuckDuckGo, également rangs ce très fortement.
- Il n'y a rien de mal à faire un absolu à l'importation comme à hasen de réponse. Ceci est fait des centaines de fois dans Django. Il est tout à fait acceptable. Dans certains cas, faire un par rapport à l'importation est plus agréable et plus courtes, donc n'hésitez pas à utiliser ces méthodes de façon interchangeable.
- Mon avis a changé depuis Absolus des Importations. Relative des importations sont sympas, mais "Explicite est mieux qu'Implicite" et, dans une moindre mesure, "les espaces de noms sont un "honkin grande idée"
- mais j'ai entendu relative des importations est considéré comme un mauvais comportement?
- Vous pouvez prendre un coup d'oeil à ce guide définitif chrisyeh96.github.io/2017/08/08/...
- Je recommande fortement de sauter passé tous les
sys.path
ouPYTHONPATH
réponses et check out np8 excellente réponse. Oui, c'est long à lire. Oui, il ressemble à beaucoup de travail. Mais c'est la seule réponse qui résout effectivement le problème correctement et proprement. - Qu'est-il arrivé à l'exécutable de pseudo? Pourquoi est-il une telle douleur pour importer des modules à partir d'un dossier parent en Python? Ce qui est absurde.
- Il est difficile que si vous êtes incohérent: à l'aide d'un fichier de mise en page appropriée pour un paquet (compliqué, bibliothque, de qui de votre script, mais un client), mais d'essayer de l'exécuter comme un jetable script (sans même
python -m
).
Vous devez vous connecter pour publier un commentaire.
Il semble que le problème n'est pas lié au module dans un répertoire parent ou quelque chose comme ça.
Vous devez ajouter le répertoire qui contient
ptdraft
à PYTHONPATHVous avez dit que
import nib
travaillé avec vous, que signifie probablement que vous avez ajoutéptdraft
lui-même (et pas de ses parents) à PYTHONPATH.import sys
et puissys.path.append("..\<parent_folder>")
Vous pouvez utiliser par rapport aux importations (python >= 2.5):
(Ce qui est Nouveau dans Python 2.5) PEP 328: Absolue et Relative des Importations
MODIFIER: ajout d'un autre point '.' pour aller jusqu'à deux paquets
ValueError: Attempted relative import in non-package
__init__.py
fichier.__init__.py
n'est pas la seule chose que vous avez à faire: stackoverflow.com/questions/11536764/...__init__.py
fichier.__init__.py
dans le répertoire parent.python -m
, par exemple, dans ce caspython -m ptdraft.nib
. Toutes les importations puis obtenir correctement résolu, voir PEP338.Relative des importations (comme dans
from .. import mymodule
) ne fonctionnent que dans un paquet.Pour importer 'mymodule" qui est dans le répertoire parent de votre module:
modifier: le
__file__
attribut n'est pas toujours le cas. Au lieu d'utiliseros.path.abspath(__file__)
j'ai alors proposé à l'aide de l'inspecter module pour récupérer le nom de fichier (chemin) du fichier en courssys.path.insert(1, os.path.join(sys.path[0], '..'))
parentdir
, mais dans un des chemins déjà spécifié danssys.path
, il y a un autre module avec le nom "mymodule'. L'insertion de laparentdir
que le premier élément de lasys.path
liste assure que le module deparentdir
sera importé à la place.sys.path.insert(1, os.path.realpath(os.path.pardir))
travaille trop.J'ai posté une semblable réponse à la question concernant les importations à partir de la fratrie des paquets. Vous pouvez le voir, il ici. Ce qui suit est testé avec Python 3.6.5, (Anaconda, conda 4.5.1), Windows 10 de la machine.
Solution sans sys.chemin des hacks
Installation
Je suppose que la même structure de dossier dans la question
J'appelle le
.
le dossier racine, et dans mon cas il est situé dansC:\tmp\test_imports
.Étapes
1) Ajouter un setup.py à la racine du dossier
Le contenu de la
setup.py
peut être simplementEn gros "tout" setup.py serait de travailler. C'est juste un minimum de travail par exemple.
2) l'Utilisation d'un environnement virtuel
Si vous êtes familier avec les environnements virtuels, activer une, et passez à l'étape suivante. L'utilisation d'environnements virtuels ne sont pas absolument nécessaires, mais ils vraiment vous aider dans le long terme (si vous avez plus de 1 projet en cours..). La plupart des étapes de base sont (exécuter dans le dossier racine)
python -m venv venv
. /venv/bin/activate
(Linux) ou./venv/Scripts/activate
(Win)Pour en savoir plus à ce sujet, juste Google "à" python virtuel env tutoriel" ou similaire. Vous n'avez probablement jamais besoin de toutes les autres commandes de la création, de l'activation et de la désactivation.
Une fois que vous avez fait et activé un environnement virtuel, votre console devrait donner le nom de l'environnement virtuel dans la parenthèse
3) pip install votre projet modifiable état
L'installation de votre haut niveau,
myproject
à l'aide depip
. L'astuce est d'utiliser le-e
drapeau lors de l'installation. De cette manière, il est installé modifiable dans un état, et toutes les modifications apportées à l' .py fichiers seront automatiquement inclus dans le paquet installé.Dans le répertoire de racine, exécutez
pip install -e .
(notez le point, il est synonyme de "répertoire courant")Vous pouvez aussi voir qu'il s'est installé à l'aide de
pip freeze
4) l'Importation en ajoutant
mainfolder
à chaque importationDans cet exemple, le
mainfolder
seraitptdraft
. Ceci a l'avantage que vous n'aurez pas de nom de collisions avec d'autres noms de module (à partir de la bibliothèque standard de python ou 3ème partie des modules).Exemple D'Utilisation
nib.py
life.py
De course life.py
sys.path
et où le code pourra généralement être installé par les utilisateurs finaux. C'est mieux quesys.path
hacks (et vous pouvez inclure l'utilisation de PYTHONPATH dans cette catégorie de chemin de hacks), car elle signifie que le code dans le développement devrait se comporter de la même manière pour vous comme pour les autres utilisateurs. En revanche, lors de l'utilisation de chemin de modifications, les déclarations d'importation pourrait être résolu d'une manière différente.requirements.txt
?pip uninstall package-name
, et le nom du package peut être lu à partir depip list
.Si l'ajout de votre dossier du module pour le PYTHONPATH ne fonctionne pas, Vous pouvez modifier la sys.chemin liste dans votre programme où l'interpréteur Python recherches pour les modules à importer, la la documentation python dit:
Sachant cela, vous pouvez effectuer les opérations suivantes dans votre programme:
/path/to/ptdraft
devrait être édité. Il existe des solutions qui fonctionnent le répertoire courant du fichier et l'importer à partir du dossier parent de cette manière aussi.Vous pouvez utiliser l'OS en fonction chemin d'accès dans le module "chemin de recherche" qui est répertorié dans sys.chemin .
Donc, vous pouvez facilement ajouter le répertoire parent comme suit
Si vous voulez ajouter un parent-parent directory,
Ne sais pas beaucoup sur python 2.
En python 3, le dossier parent peut être ajouté comme suit:
...et puis on est capable d'importer des modules de il
'..'
conduit dans le répertoire du module en question.Ici est une réponse simple, donc vous pouvez voir comment il fonctionne, de petites et de croix-plateforme.
Il utilise uniquement les modules intégrés (
os
,sys
etinspect
) devrait donc du travailsur n'importe quel système d'exploitation (OS) parce que Python est conçu pour que.
Plus court code de réponse de moins en moins de lignes et les variables
Pour les moins de lignes que ce, remplacer la deuxième ligne avec
import os.path as path, sys, inspect
,ajouter
inspect.
au début degetsourcefile
(ligne 3) et de supprimer la première ligne.- toutefois cette importations de tous les module pourrait donc besoin de plus de temps, de mémoire et de ressources.
Le code de ma réponse (version longue)
Il utilise un exemple à partir d'un Débordement de Pile réponse Comment puis-je obtenir le chemin d'accès courant
le fichier exécuté en Python? de trouver la source (nom de fichier) d'exécuter du code avec un outil intégré.
Mon code ajoute un chemin d'accès au fichier à
sys.path
, le python path listeparce que cela permet de Python pour importer des modules à partir de ce dossier.
Après l'importation d'un module dans le code, c'est une bonne idée d'exécuter
sys.path.pop(0)
sur une nouvelle lignelorsque ce dossier ajouté a un module avec le même nom qu'un autre module est importé
plus tard dans le programme. Vous devez supprimer l'élément de la liste est ajoutée avant l'importation, et non sur d'autres chemins.
Si votre programme n'a pas importer d'autres modules, il est sûr de ne pas supprimer le chemin d'accès au fichier car
après un programme se termine (ou le redémarrage de l'interface Python), toutes les modifications apportées à
sys.path
disparaître.Des Notes sur un nom de fichier variable
Ma réponse n'utilise pas le
__file__
variable pour obtenir le chemin d'accès au fichier/nom de fichier de l'exécutioncode parce que les utilisateurs ont souvent décrit comme peu fiables. Vous ne devriez pas l'utiliser
pour de l'importation de modules dossier parent dans les programmes utilisés par d'autres personnes.
Quelques exemples où il ne fonctionne pas (citation de cette Débordement de Pile question):
• il ne peut pas être trouvé sur certaines plates-formes • il est parfois n'est-ce pas le chemin complet du fichier
sys.path.pop(0)
immédiatement après l'importation du module souhaité. Toutefois, les importations ultérieures allaient encore à cet endroit. Par exemple, j'aiapp/config
,app/tools
etapp/submodule/config
. Desubmodule
, j'ai insérerapp/
à l'importationtools
, puis retirezapp/
et essayez d'importerconfig
, mais je reçoisapp/config
au lieu deapp/submodule/config
.tools
's des importations a été également l'importation deconfig
du parent dir. Alors quand j'ai essayé plus tard de fairesys.path.pop(0); import config
à l'intérieur desubmodule
, s'attendant à obtenirapp/submodule/config
, j'ai été réellement obtenirapp/config
. Évidemment, Python renvoie une version en cache d'un module du même nom, au lieu de vérifier effectivement lessys.path
pour un module correspondant à ce nom.sys.path
dans ce cas a été modifié correctement, Python a été tout simplement pas le vérifier en raison du même nom module a déjà été chargé.sys.modules
... sys.des modules est accessible en écriture. La suppression d'une clé invalide le cache d'entrée pour le module, provoquant Python à la recherche de nouveau lors de sa prochaine importation. ... Attention cependant, car si vous gardez une référence à l'objet module, d'invalider le cache puis de le ré-importer, les deux objets sont différents. En revanche,importlib.reload()
de réutilisation et de réinitialiser le module contenu ...os.path.realpath(getsourcefile(lambda:0) + "/../..")
. Obtenez de source de courant de fichier ajouté avec deux parents répertoire de symboles. Je n'ai pas utiliséos.path.sep
commegetsourcefile
était renvoie une chaîne à l'aide de/
même sur Windows.realpath
prendra soin de sauter des deux entrées de l'annuaire à partir du chemin d'accès complet (dans ce cas, le nom du fichier et le répertoire courant) qui donne le répertoire parent.Ici est plus de solution générique qui inclut le répertoire parent dans sys.chemin d'accès (pour moi):
import os, sys\n sys.path.insert(0,os.path.pardir)
même chose, mais sorther 🙂 (pas de sauts de ligne dans les commentaires)os.path.pardir
vous ne sera pas obtenir de la fonction realpath de la mère, juste chemin relatif à partir d'où vous appelez lesys.path.insert()
__file__
variable qui peut être fiable (n'est-ce pas toujours le chemin complet du fichier, ne fonctionne pas sur tous les systèmes d'exploitation, etc.) comme StackOverflow les utilisateurs ont souvent mentionné. La modification de la réponse pour ne pas l'inclure causera moins de problèmes et plus de la croix-compatible. Pour plus d'informations, voir stackoverflow.com/a/33532002/3787376.J'ai trouvé la façon suivante fonctionne pour l'importation d'un package à partir du script du répertoire parent. Dans l'exemple, je voudrais importer des fonctions dans
env.py
deapp.db
paquet.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'une certaine manière (par exemple,PYTHONPATH
) pour votre bibliothèque pour être accessible à autres code (ou autre chose, elle n'est pas vraiment une bibliothèque); il suffit de l'utiliser tout le temps!Pour moi, le plus court et mon préféré oneliner pour accéder au répertoire parent est:
ou:
os.getcwd() retourne le nom du répertoire de travail courant, os.chemin d'accès.dirname(directory_name) renvoie le nom du répertoire pour le passé une.
En fait, à mon avis Python projet d'architecture doit être fait de la façon où les pas de l'un des modules de l'enfant répertoire d'utiliser n'importe quel module dans le répertoire parent. Si quelque chose comme cela arrive, il vaut la peine de repenser à propos de l'arborescence du projet.
Une autre façon est d'ajouter le répertoire parent de PYTHONPATH variable d'environnement système.
import sys
sys.path.append('../')
Solutions mentionnées ci-dessus sont aussi très bien. Une autre solution à ce problème est
Si vous voulez importer quoi que ce soit à partir du répertoire de premier niveau. Ensuite,
Aussi, si vous souhaitez importer un module à partir du répertoire parent. Ensuite,
Aussi, si vous souhaitez importer un module à partir du répertoire parent. Ensuite,
De cette façon, vous pouvez importer une méthode en particulier si vous le souhaitez.
sys.path.append
hacks ci-dessus et je ne peux pas importer mes lib comme ça. C'est ce que j'ai d'abord essayé de le faire avant de commencer à google 🙂 Ok, c'est cetteValueError: attempted relative import beyond top-level package
Lorsqu'il n'est pas dans un paquet de l'environnement avec
__init__.py
fichiers de la pathlib bibliothèque (inclus avec >= Python 3.4) le rend très concise et intuitive pour ajouter le chemin d'accès du répertoire parent pour le PYTHONPATH:même genre de style que le passé de réponse mais en moins de lignes 😛
fichier renvoie l'emplacement que vous travaillez dans
__file__
variable qui peut être fiable (n'est-ce pas toujours le chemin complet du fichier, ne fonctionne pas sur tous les systèmes d'exploitation, etc.) comme StackOverflow les utilisateurs ont souvent mentionné. La modification de la réponse pour ne pas l'inclure causera moins de problèmes et plus de la croix-compatible. Pour plus d'informations, voir stackoverflow.com/a/33532002/3787376.Travail avec les bibliothèques.
Faire une bibliothèque appelée plume, de l'installer à l'aide de setup.py, laissez résident dans site-packages et vos problèmes sont résolus.
Vous n'avez pas à farcir tout ce que vous faites dans un seul paquet. Le briser, mettre en pièces.
site-packages
chaque fois qu'ils l'exécuter sur un autre ordinateur.Dans un Jupyter Portable avec Linux
Aussi longtemps que vous travaillez dans un Jupyter Notebook, cette solution pourrait être utile:
Il fonctionne même sans
__init__.py
fichier.Dans un système Linux, vous pouvez créer un doux lien de la "vie" du dossier à la nib.py fichier. Ensuite, vous pouvez simplement importer comme:
Solution Simple pour le chemin d'accès absolu dans windows 10:
cela la fonction d'importation des "function_name"
de: C:\Users\user01\Desktop\pipeline\folder1\folder2\filename