976 votes

Python relative des importations pour la milliardième fois

J'ai été ici

et beaucoup d'Url que je n'ai pas de copie, de certains, de certains sur d'autres sites, à l'époque où je pensais J'aurais la solution rapidement.

Le forever récurrents question est: est-ce Avec Windows 7, 32 bits Python 2.7.3, comment puis-je résoudre ce "Tentative relative à l'importation de non-package" message? J'ai construit une réplique exacte de l'emballage sur pep-0328:

package/

    __init__.py

    subpackage1/

        __init__.py

        moduleX.py

        moduleY.py

    subpackage2/

        __init__.py

        moduleZ.py

    moduleA.py

J'ai fait des fonctions nommé spam et les œufs dans leurs modules appropriés. Naturellement, cela n'a pas fonctionné. La réponse est apparemment dans le 4ème URL que j'ai énumérés, mais il est de tous les anciens de moi. Il y a eu cette réponse sur l'une des Url que j'ai visité:

Relative des importations de l'utilisation d'un module du nom de l'attribut pour déterminer le module de la position dans la hiérarchie des paquets. Si le module est le nom ne contient pas toute l'information de l'emballage (par exemple, il est à 'principal') puis par rapport importations sont résolus que si le module ont été d'un haut niveau module, indépendamment de l'endroit où le module est en fait situé sur le système de fichiers.

La réponse ci-dessus semble prometteur, mais il est tout hiéroglyphes pour moi. Donc ma question, comment puis-je faire Python pas de retour pour moi "a Tenté relative à l'importation de non-package"? a une réponse qui implique -m, soi-disant.

Quelqu'un peut-il me dire pourquoi Python donne ce message d'erreur, ce qu'il Entend par non-package!, pourquoi et comment définir un "package", et la réponse précise à poser en termes assez facile pour un kindergartener à comprendre. Merci à l'avance!

Edit: Les importations ont été effectuées à partir de la console.

1369voto

BrenBarn Points 63718

Voici une explication. La version courte est qu'il y a une grande différence entre directement l'exécution d'un fichier Python, et l'importation de ce fichier à partir de quelque part d'autre. De savoir que ce répertoire un fichier ne permet pas de déterminer quel paquet Python pense qu'il est dans. Cela dépend, en outre, sur la façon dont vous chargez le fichier en Python (en cours d'exécution ou par l'importation).

Il y a deux façons de charger un fichier Python: le script de niveau supérieur, ou comme un le module. Un fichier est chargé dans le script de niveau supérieur si vous l'exécuter directement, par exemple en tapant python myfile.py sur la ligne de commande. Il est chargé en tant que module si vous n' python -m myfile, ou s'il est chargé lorsque l' import déclaration est encounted à l'intérieur d'un autre fichier. Il peut seulement être un script de niveau supérieur à un temps; le script de niveau supérieur est le fichier Python vous avez exécuté, pour commencer.

Lorsqu'un fichier est chargé, il est donné un nom (qui est stocké dans ses __name__ d'attribut). Si il a été chargé comme le script de niveau supérieur, son nom est __main__. Si il a été chargé en tant que module, son nom est le nom de fichier, précédé par le nom de tous les ensembles/sous-paquets dont il fait partie, séparés par des points.

Ainsi, par exemple, dans votre exemple, si vous avez importé moduleX (note: importés, ne sont pas directement exécuté), son nom serait package.subpackage1.moduleX. Si vous avez importé moduleA, son nom serait package.moduleA. Toutefois, si vous exécutez directement moduleX à partir de la ligne de commande, son nom sera à la place __main__, et si vous exécutez directement moduleA à partir de la ligne de commande, son nom sera __main__. Lorsqu'un module est exécuté le script de niveau supérieur, il perd son nom normal et son nom est plutôt __main__.

Il existe une ride: le module du nom dépend de si elle a été importée "directement" à partir du répertoire il est ou importés par l'intermédiaire d'un package. Cela ne fait qu'une différence si vous exécutez Python dans un répertoire, et essayez d'importer un fichier dans le même répertoire (ou un sous-répertoire de celui-ci). Par exemple, si vous lancez l'interpréteur Python dans le répertoire package/subpackage1 puis effectuez l' import moduleX, le nom de l' moduleX sera moduleX, et pas package.subpackage1.moduleX. C'est parce que Python ajoute le répertoire courant de son chemin de recherche sur le démarrage; si elle trouve le pour-être-module importé dans le répertoire courant, il ne saura pas que ce répertoire est partie d'un paquet et le paquet de l'information ne font pas partie intégrante du module du même nom.

Un cas spécial est de savoir si vous exécutez l'interprète de manière interactive (par exemple, il suffit de taper python et de commencer la saisie du code Python à la volée). Dans ce cas, le nom de cette session interactive est - __main__.

Maintenant, voici la chose cruciale pour votre message d'erreur: si le nom d'un module n'a pas de points, il n'est pas considéré comme faisant partie d'un package. Il n'a pas d'importance où le fichier est en fait sur le disque. Tout ce qui compte c'est ce que son nom, et son nom dépend de la façon dont vous l'a chargé.

Regardez maintenant le devis que vous avez inclus dans votre question:

Relative des importations de l'utilisation d'un module du nom de l'attribut pour déterminer le module de la position dans la hiérarchie des paquets. Si le module est le nom ne contient pas toute l'information de l'emballage (par exemple, il est à 'principal') puis par rapport importations sont résolus que si le module ont été d'un haut niveau module, indépendamment de l'endroit où le module est en fait situé sur le système de fichiers.

Relative des importations de l'utilisation du module de nom afin de déterminer où il se trouve dans un paquet. Lorsque vous utilisez l'un par rapport à l'importation comme from .. import foo, les points de suspension indiquent à l'étape jusqu'certain nombre de niveaux dans la hiérarchie des paquets. Par exemple, si votre module en cours nom de l' package.subpackage1.moduleX, alors ..moduleA signifierait package.moduleA. Pour un from .. import de travail, le module du nom doit avoir au moins autant de points qu'il y a dans la import déclaration.

Toutefois, si votre module est le nom est __main__, il n'est pas considéré comme un paquet. Son nom n'a pas de points, et, par conséquent, vous ne pouvez pas utiliser from .. import états à l'intérieur. Si vous essayez de le faire, vous obtiendrez le "relatif à l'importation dans la non-package" erreur.

Ce que vous avez probablement fait, c'est que vous avez essayé d'exécuter moduleX ou à partir de la ligne de commande. Lorsque vous avez fait cela, son nom a été mis à l' __main__, ce qui signifie que, par rapport des importations à l'intérieur, il sera un échec, car son nom ne révèle pas qu'il est dans un package. Notez qu'il sera également se produire si vous exécutez Python dans le même répertoire où se trouve un module, puis essayez d'importer ce module, parce que, comme décrit ci-dessus, Python trouverez le module dans le répertoire courant "trop tôt" sans se rendre compte qu'il fait partie d'un package.

Rappelez-vous aussi que lorsque vous exécutez l'interactive interprète, le "nom" de cette session interactive est toujours __main__. Donc vous ne pouvez pas le faire par rapport importations directement à partir d'une session interactive. Relative des importations sont uniquement pour l'utilisation dans le module de fichiers.

Il y a deux solutions à cela. Si vraiment vous ne voulez pas exécuter moduleX directement, mais vous voulez toujours être considéré comme faisant partie d'un package, vous pouvez le faire python -m package.subpackage.moduleX. L' -m indique à Python pour charger un module, non pas comme le script de niveau supérieur.

Ou peut-être vous n'avez pas vraiment envie de courir moduleX, vous voulez juste pour exécuter un script, dire myfile.py, qui utilise des fonctions à l'intérieur d' moduleX. Si c'est le cas, placez myfile.py ailleurs --- pas à l'intérieur de l' package annuaire, et l'exécuter. Si à l'intérieur d' myfile.py vous faire des choses comme from package.moduleA import spam, cela fonctionnera très bien.

À noter que pour l'une de ces solutions, le répertoire du package (package dans l'exemple) doit être accessible à partir du module Python chemin de recherche (sys.path). Si elle n'est pas, vous ne serez pas en mesure d'utiliser quoi que ce soit dans le package de façon fiable à tous.

(Une technique remarque: depuis la version 2.6 de Python, le module de "nom" pour le paquet de résolution est déterminée non seulement par ses __name__ attributs, mais aussi par l' __package__ d'attribut. C'est pourquoi j'évite d'utiliser le symbole explicite __name__ de vous référer au module "nom". Depuis la version 2.6 de Python d'un module "nom" est efficacement __package__ + '.' + __name__, ou juste __name__ si __package__ est None.)

2voto

theodox Points 3983

__nom__ change selon que le code en question est exécuté dans l'espace de noms global ou dans le cadre d'un module importé.

Si le code n'est pas exécuté dans l'espace mondial, le nom sera le nom du module. Si elle est en cours d'exécution dans l'espace de noms global, par exemple, si vous tapez dans une console, ou d'exécuter le module comme un script à l'aide de "python.exe yourscriptnamehere.py" alors __nom__ devienne __principaux__.

Vous verrez beaucoup de code python avec 'if __name__ == '__principaux__ " est utilisé pour tester si le code est exécuté à partir de l'espace de noms global -- qui vous permet d'avoir un module qui se double d'un script.

Avez-vous essayer de faire ces importations à partir de la console?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X