au-delà de haut niveau, d'erreur relatifs à l'importation
Il semble qu'il y a déjà pas mal de questions à propos relatif à l'importation en python 3, mais après être passé par beaucoup d'entre eux je n'ai toujours pas trouver la réponse à ma question.
donc, voici la question.
J'ai un forfait indiqué ci-dessous
package/
__init__.py
A/
__init__.py
foo.py
test_A/
__init__.py
test.py
et j'ai une seule ligne dans test.py:
from ..A import foo
maintenant, je suis dans le dossier de package
, et je
python -m test_A.test
J'ai eu le message
"ValueError: attempted relative import beyond top-level package"
mais si je suis dans le dossier parent de package
, par exemple, je lance:
cd ..
python -m package.test_A.test
tout va bien.
Maintenant, ma question est:
quand je suis dans le dossier de package
, et je lance le module à l'intérieur de la test_A sous-package comme test_A.test
, selon ma compréhension, ..A
monte d'un seul niveau, qui est toujours à l'intérieur de la package
dossier, pourquoi il donne le message beyond top-level package
. Ce qui est exactement la raison qui provoque ce message d'erreur?
- double possible de Comment faire par rapport importations en Python?
- ce post n'a pas pour expliquer mon "au-delà de haut niveau," erreur
- J'ai une pensée ici, de sorte que lorsque vous exécutez test_A.test en tant que module, ‘..' passe au dessus de la test_A, ce qui est déjà le plus haut niveau de l'importation test_A.test, je pense que le package n'est pas le niveau de répertoire, mais combien de niveaux vous importer le package.
- Je vous promets que vous comprenez tout ce qui est sur par rapport à l'importation après avoir vu cette réponse de stackoverflow.com/a/14132912/8682868.
Vous devez vous connecter pour publier un commentaire.
EDIT: Il y a de mieux/plus cohérente à cette question des réponses à d'autres questions:
Pourquoi ne pas travailler? C'est parce que python n'enregistre pas si l'emballage a été chargé de. Ainsi, lorsque vous vous
python -m test_A.test
, qu'il est fondamentalement juste les rejets de la connaissance quetest_A.test
est en fait stockée danspackage
(c'est à direpackage
n'est pas considéré comme un paquet). La tentativefrom ..A import foo
essaie d'accéder à l'information qu'il n'a pas plus du tout (c'est à dire des répertoires frère de l'un chargé de l'emplacement). C'est conceptuellement similaire à l'permettantfrom ..os import path
dans un fichier dansmath
. Ce serait mauvais parce que vous voulez que les paquets distincts. S'ils ont besoin d'utiliser quelque chose d'un autre paquet, puis ils doivent se référer à l'échelle mondiale, avecfrom os import path
et laissez python travail où c'est avec$PATH
et$PYTHONPATH
.Lorsque vous utilisez
python -m package.test_A.test
, puis à l'aidefrom ..A import foo
résout très bien parce qu'elle a gardé la trace de ce qui est danspackage
et vous êtes tout simplement l'accès à un répertoire enfant d'un chargé emplacement.Pourquoi ne pas python envisager le répertoire de travail actuel pour être un paquet? AUCUNE IDÉE de, mais en gros ça serait utile.
-m
le drapeau et l'exécuter à partir du répertoire ci-dessus.sys.path
hack, mais l'utilisation de setuptools, qui est beaucoup plus intéressant à mon avis.De l'essayer.
A travaillé pour moi.
A/bar.py
existe et dansfoo.py
vous nefrom .bar import X
.Hypothèse:
Si vous êtes dans le
package
répertoire,A
ettest_A
sont des paquets séparés.Conclusion:
..A
les importations ne sont permis dans un paquet.Note en outre:
Faire de la relative importations uniquement disponible au sein d'ensembles est utile si vous voulez forcer que les paquets peuvent être placés sur n'importe quel chemin d'accès situé sur
sys.path
.EDIT:
Le répertoire de travail courant est généralement situé dans sys.chemin d'accès. Ainsi, tous les fichiers y sont importables. C'est un comportement depuis Python 2 quand les paquets n'existait pas encore. Rendre le répertoire d'exécution d'un package d'autoriser les importations de modules "à l'importation .Un" et que "l'importation d'Un" qui serait alors de deux modules différents. C'est peut-être une incohérence à prendre en compte.
python -m package.test_A.test
semble faire ce qu'ils voulaient, et mon argument est que cela devrait être la valeur par défaut. Donc, pouvez-vous me donner un exemple de cette incompatibilité?from package.A import foo
Je pense que c'est plus clair que
sys.path.append("..")
. testé sur python 3.6Aucune de ces solutions n'a fonctionné pour moi en 3.6, avec une structure de dossier comme:
Mon but était de les importer à partir dans module2 module1. Ce qui a finalement fonctionné pour moi a été, curieusement:
Note le seul point plutôt que deux-point des solutions mentionnées ci-dessus.
Edit: ce qui suit a permis de clarifier cela pour moi:
Dans mon cas, le répertoire de travail a (inattendue) de la racine du projet.
Si quelqu'un essaie encore un peu après le grand les réponses déjà fournies, envisager de vérifier ce:
https://www.daveoncode.com/2017/03/07/how-to-solve-python-modulenotfound-no-module-named-import-error/
Essentielles de devis à partir du site ci-dessus:
Il est assez évident qu'il a à être de cette façon, la pensée sur elle après le fait. J'ai essayé d'utiliser le sys.chemin d'accès.append('..') dans mes tests, mais a couru dans la question posté par OP. En ajoutant l'importation et sys.chemin de définition avant mes autres importations, j'ai été en mesure de résoudre le problème.
Comme la réponse la plus populaire suggère, fondamentalement, de son parce que votre
PYTHONPATH
ousys.path
comprend.
mais pas votre chemin d'accès à votre package. Et le rapport de l'importation est relatif au répertoire de travail courant, pas le fichier où l'importation se passe; bizarrement.Vous pouvez résoudre ce problème en modifiant tout d'abord votre relatif à l'importation à l'absolu, et ensuite, soit qu'il commence par:
OU en forçant le python path lorsqu'il est appelé de cette façon, parce que:
Avec
python -m test_A.test
vous êtes l'exécution detest_A/test.py
avec__name__ == '__main__'
et__file__ == '/absolute/path/to/test_A/test.py'
Qui signifie que dans le
test.py
vous pouvez utiliser votre absolueimport
semi-protégé dans l'affaire principale condition, et aussi faire un temps de Python chemin de la manipulation:si vous avez un
__init__.py
dans un dossier de niveau supérieur, vous pouvez initialiser les importer en tant queimport file/path as alias
dans ce fichier init. Ensuite, vous pouvez l'utiliser sur le bas-scripts: