Besoin de __name__ == "__main__" comme indiqué dans les problèmes d'importation circulaire

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.

Maintenant, avec cela à l'esprit, vérifions ce qui se passe lorsque nous exécutons le précédent " python3 piyo.py ".

  1. Dans " piyo.py "," ʻimport hoge "et hoge.pysont importés. À ce stade, la classePiyo` n'a pas encore été définie.
  2. Dans le " hoge.py "importé," ʻimport piyo"est exécuté, mais comme"piyo.py`" est déjà chargé, il ne fait rien.
  3. La classe 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 ".

  1. Dans " hoge.py "," ʻimport piyo "et piyo.py` sont importés. À ce stade, les classes «Base» et «Hoge» ne sont pas définies.
  2. Dans le " piyo.py "importé," ʻimport hoge"est exécuté, mais comme"hoge.py`" est déjà chargé, il ne fait rien.
  3. La classe 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.

Sur cette base, vérifions à nouveau le fonctionnement de " python3 piyo.py ".

  1. Dans " piyo.py "," ʻimport hoge "et hoge.pysont importés. À ce stade, la classePiyo` n'a pas encore été définie.
  2. Dans le " 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.
  3. Dans le " piyo.py "importé," ʻimport hoge"est exécuté, mais comme"hoge.py`" est déjà chargé, il ne fait rien.
  4. Fait référence à la classe 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.

Recommended Posts

Besoin de __name__ == "__main__" comme indiqué dans les problèmes d'importation circulaire
Besoin de __name__ == "__main__" comme indiqué dans les problèmes d'importation circulaire
Rechercher des chaînes dans les fichiers
Techniques de tri en Python
À propos de "for _ in range ():" de python
À propos de la nécessité d'une première barre oblique dans le nom de l'abonné et le nom de l'éditeur
À propos de la nécessité d'une première barre oblique dans le nom de l'abonné et le nom de l'éditeur