Circulaire (ou cyclique) importations en Python
Ce qui va se passer si deux modules d'importation les uns des autres?
De généraliser le problème, ce qui sur le cyclique des importations en Python?
- Voir aussi stackoverflow.com/questions/158268/...
- également comme une référence, il semble circulaire importations sont autorisées sur python 3.5 (et probablement au-delà), mais pas de 3,4 (et probablement ci-dessous).
- Je suis à l'aide de python 3.7.2 et suis encore avoir une erreur d'exécution en raison des dépendances circulaires.
Vous devez vous connecter pour publier un commentaire.
Il y avait vraiment une bonne discussion sur ce fil à comp.lang.python l'année dernière. Il répond à votre question très soigneusement.
Si vous ne
import foo
à l'intérieur debar
etimport bar
à l'intérieur defoo
, cela fonctionnera très bien. Par le temps que tout fonctionne en fait, les deux modules sera entièrement chargé et aura des références à l'autre.Le problème, c'est quand au lieu de cela, vous ne
from foo import abc
etfrom bar import xyz
. Parce que maintenant chaque module nécessite l'autre module d'ores et déjà être importés (de sorte que le nom, nous sommes importateurs existe) avant d'être importé.from foo import *
etfrom bar import *
fonctionne également très bien.from x import y
, et pourtant obtient la circulaire d'erreur d'importationimport
instruction est exécutée. Il n'est donc pas d'erreur, mais vous ne pouvez pas obtenir toutes les variables que vous attendez.from foo import *
etfrom bar import *
, le tout exécuté dans lefoo
est dans l'initialisation de la phase debar
, et les fonctions dansbar
n'a pas encore été défini...Cyclique des importations de mettre fin, mais vous devez être prudent de ne pas utiliser les variations conjoncturelles modules importés au cours de l'initialisation du module.
Envisager les fichiers suivants:
un.py:
b.py:
Si vous exécutez une.py, vous aurez la suivante:
Sur la deuxième importation de b.py (dans la deuxième
a in
), l'interpréteur Python ne pas importerb
de nouveau, car il existe déjà dans le module dict.Si vous essayez d'accéder à
b.x
dea
lors de l'initialisation du module, vous obtiendrez unAttributeError
.Ajouter la ligne suivante à
a.py
:Ensuite, la sortie est:
C'est parce que les modules sont exécutés sur l'importation et à l'époque
b.x
est accessible, la lignex = 3
a pas exécuté, ce qui ne sera possible aprèsb out
.Comme d'autres réponses décrire ce modèle est acceptable en python:
Qui permettra d'éviter l'exécution de l'instruction d'importation lorsque le fichier est importé par d'autres modules. Seulement si il y a une logique de dépendance circulaire, ce sera un échec.
Plus Circulaire, les Importations ne sont pas réellement logique circulaire importations, mais plutôt de soulever
ImportError
erreurs, en raison de la façonimport()
évalue haut niveau consolidés de l'ensemble du dossier lors de l'appel.Ces
ImportErrors
peut presque toujours être évitée si vous positivement voulez que votre importations sur le dessus:Considérer la présente circulaire d'importation:
Application D'Un
Application B
De David Beazleys excellent exposé Modules et Packages: Vivre et Laisser Mourir! - PyCon 2015,
1:54:00
, voici une façon de traiter avec la circulaire importations en python:Cette tente d'importer
SimplifiedImageSerializer
et siImportError
est élevé, car il est déjà importé, il va tirer de la importcache.PS: Vous devez lire l'intégralité de ce post de David Beazley la voix.
J'ai un exemple ici qui m'a frappé!
foo.py
bar.py
main.py
À la ligne de commande: $ python main.py
import bar
dansfoo.py
à la finbar
etfoo
les deux doivent utilisergX
, le "plus propre", la solution est de mettregX
dans un autre module et à la foisfoo
etbar
importer ce module. (la plus propre dans le sens où il n'y a pas masqué sémantique dépendances.)bar
ne pouvez même pas trouvergX
dans le foo. l'importation circulaire est bien par lui-même, mais c'est juste quegX
n'est pas défini quand il est importé.Je suis complètement d'accord avec pythoneer de réponse ici. Mais je suis tombé sur un code qui a été vicié par la circulaire importations et cause des problèmes lorsque vous essayez d'ajouter des tests unitaires. Donc, pour rapidement patch sans changer tout ce que vous pouvez résoudre le problème en faisant une dynamique d'importation.
Encore une fois, ce n'est pas une solution permanente, mais peut aider quelqu'un qui veut corriger une erreur d'importation sans changer trop de code.
Cheers!
Module un.py :
Module b.py
L'exécution du Module "a" sera de sortie:
La sortie de ce 3 lignes alors qu'il était censé sortie infinitival en raison de la circulaire de l'importation.
Ce qui se passe, ligne par ligne lors de l'exécution de"Module" est répertorié ici:
import b
. donc, il va visiter le module bimport a
. donc, il va visiter un moduleimport b
mais noter que cette ligne ne sera pas exécutée de nouveau plus, car tous les fichiers python exécuter une ligne d'importation pour une fois, il n'importe pas où ou quand il est exécuté. donc, il va passer à la ligne suivante et imprimer"This is from module a"
."This is from module b"
"This is from module a"
et le programme sera terminé.Circulaire importations peut être source de confusion en raison de l'importation fait deux choses:
Que le premier est en fait qu'une seule fois, tandis que la seconde, à chaque instruction d'importation. Importation circulaire crée de la situation lors de l'importation de module utilise importe partiellement le code exécuté. En conséquence, il ne sera pas voir les objets créés après l'instruction d'importation. Ci-dessous exemple de code montre.
Circulaire importations ne sont pas le mal ultime, à éviter à tout prix. Dans certains cadres comme Fiole ils sont tout à fait naturelles et de peaufiner votre code pour les éliminer ne pas rendre le code mieux.
main.py
b.by
un.py
python main.py sortie avec les commentaires
J'ai résolu le problème de la manière suivante, et il fonctionne bien sans aucune erreur.
Considérons deux fichiers
a.py
etb.py
.J'ai ajouté ceci à
a.py
et cela a fonctionné.un.py:
b.py:
La sortie que je vous est
Cela pourrait être une autre solution a fonctionné pour moi.
Ok, je pense que j'ai une super solution.
Disons que vous avez un fichier
a
et fichierb
.Vous avez un
def
ou unclass
dans le fichierb
que vous souhaitez utiliser dans le modulea
, mais vous avez quelque chose d'autre, soit undef
,class
ou d'une variable à partir d'un fichiera
que vous avez besoin dans votre définition ou de la classe dans le fichierb
.Ce que vous pouvez faire est, au fond de fichier
a
, après l'appel de la fonction ou de la classe dans le fichiera
qui est nécessaire dans le fichierb
, mais avant l'appel de la fonction ou de la classe à partir d'un fichierb
que vous avez besoin pour fichiera
, direimport b
Alors, et voici la partie de la clé, dans toutes les définitions ou les classes dans le fichier
b
qui ont besoin dedef
ouclass
à partir d'un fichiera
(appelonsCLASS
), vous ditesfrom a import CLASS
Cela fonctionne parce que vous pouvez importer un fichier
b
sans Python de l'exécution de l'une quelconque des déclarations d'importation en fichierb
, et donc vous échapper d'une circulaire importations.Par exemple:
Un fichier:
Fichier b:
Le tour est joué.
from a import CLASS
ne fait pas sauter l'exécution de tout le code dans un.py. Je pense que c'est ce qui se passe vraiment ici:from a import CLASS
ne fait pas sauter l'exécution de tout le code dans un.py. C'est ce qui se passe vraiment: (1) Tout le code dans un.py est exécuté comme un module spécial "__principaux__". (2) Àimport b
, le premier niveau de code dans b.py est exécuté (définition de classe B), puis le contrôle revient à "__principaux__". (3) "__principal__" par la suite, passe le contrôlego.dostuff()
. (4) lorsque dostuff() vient deimport a
, il s'exécute tout le code dans un.py nouveau, cette fois dans le module "a"; puis il les importations de l'objet de CLASSE dans le nouveau module "un". Donc en fait, ce qui fonctionne aussi bien si vous avez utiliséimport a
n'importe où dans b.py.