Il y a un problème d'importation circulaire. Par exemple
hoge.py
# coding: utf-8
import piyo
class Base:
pass
class Hoge(Base):
pass
Quand,
piyo.py
# coding: utf-8
import hoge
class Piyo(hoge.Base):
pass
Si vous avez deux scripts Python, " python3 hoge.py
"ne provoque pas d'erreur, mais si vous exécutez" python3 piyo.py
",
Traceback (most recent call last):
File "piyo.py", line 3, in <module>
import hoge
File "hoge.py", line 3, in <module>
import piyo
File "piyo.py", line 5, in <module>
class Piyo(hoge.Base):
AttributeError: partially initialized module 'hoge' has no attribute 'Base' (most likely due to a circular import)
AttributeError se produira comme ceci.
(En regardant maintenant, il dit poliment "probablement en raison d'une importation circulaire")
D'autre part, une solution est de faire de la classe Base
un script séparé et d'importer ce script à la fois depuis hoge.py
/ piyo.py
.
D'ailleurs, si un tel problème apparaît occasionnellement sur le site de questions et réponses, la réponse peut être la même que ci-dessus, mais en fait la cause de l'exception est assez profonde, et toujours "Hmm. J'étais inquiète, et quand j'ai compris la raison, j'ai pensé: "Oh, c'est celle qui m'inquiétait avant. A bientôt." Aujourd'hui, je vais en prendre note.
Maintenant, voici les spécifications Python que vous devez connaître pour comprendre la cause de ce problème.
sys.modules
avec le nom du module comme clé, et s'ils sont importés à partir de la deuxième fois, il suffit de retourner l'objet enregistré dans sys.modules
et le script du module Le traitement n'est jamais exécuté.Maintenant, avec cela à l'esprit, vérifions ce qui se passe lorsque nous exécutons le précédent " python3 piyo.py
".
piyo.py
"," ʻimport hoge "et
hoge.pysont importés. À ce stade, la classe
Piyo` n'a pas encore été définie. hoge.py
"importé," ʻimport piyo"est exécuté, mais comme"
piyo.py`" est déjà chargé, il ne fait rien.Base
et la classe Hoge
écrites après" hoge.py
" sont définies.De cette façon, il fonctionne sans aucun problème ... ça? Quelque chose est différent.
Maintenant, exécutons " python3 hoge.py
".
hoge.py
"," ʻimport piyo "et
piyo.py` sont importés. À ce stade, les classes «Base» et «Hoge» ne sont pas définies. piyo.py
"importé," ʻimport hoge"est exécuté, mais comme"
hoge.py`" est déjà chargé, il ne fait rien.hoge.Base
est référencée comme la classe dérivée de la classe Piyo
, mais la définition de la classe Base
n'est pas exécutée dans hoge.py
, donc le module hoge
Il n'y a pas de Base
dans l'attribut et j'obtiens une exception ʻAttributeError`.De cette façon, une erreur se produit ... ça?
De cette façon, si vous trouvez la cause, ce sera l'opposé de l'opération réelle. J'ai toujours un problème ici, mais je me souviens d'une autre spécification Python et je la résous.
__main__
".Sur cette base, vérifions à nouveau le fonctionnement de " python3 piyo.py
".
piyo.py
"," ʻimport hoge "et
hoge.pysont importés. À ce stade, la classe
Piyo` n'a pas encore été définie. hoge.py
"importé," ʻimport piyo "est exécuté. "
Piyo.py"est déjà chargé, mais c'est ** le nom du module est"
main" **, et le module "
piyo"n'est pas chargé, donc"
piyo à nouveau .py
"est exécuté. À ce stade, les classes Base
et Hoge
qui suivent ne sont pas en cours d'exécution, elles ne sont donc pas encore définies. piyo.py
"importé," ʻimport hoge"est exécuté, mais comme"
hoge.py`" est déjà chargé, il ne fait rien.hoge.Base
comme classe source de la classe Piyo
, mais comme la définition de la classe Base
n'est pas exécutée dans hoge.py
, le module hoge
Il n'y a pas de Base
dans l'attribut et j'obtiens une exception ʻAttributeError`.Bien sûr, vous obtiendrez une exception ʻAttributeError`. Comme test,
piyo.py
# coding: utf-8
import hoge
import sys
print('\n'.join([repr(n) for n in sys.modules.items()]))
class Piyo(hoge.Base):
pass
Jetons un coup d'oeil au contenu de sys.modules
.
('__main__', <module '__main__' from 'a/piyo.py'>)
('piyo', <module 'piyo' from '/path/to/a/piyo.py'>)
(Omis sauf nécessaire)
Comme mentionné ci-dessus, vous pouvez voir que " piyo.py
"est chargé deux fois.
Maintenant, passons en revue.
Fondamentalement, une fois qu'un script est importé, il ne sera pas exécuté deux fois, mais un script qui est exécuté au démarrage peut être exécuté deux fois. Par conséquent, le script qui est exécuté au démarrage est
if __name__ == '__main__':
main()
Donc, vous devriez regarder le nom de votre module et ne l'exécuter que la première fois.