[PYTHON] Notwendigkeit für __name__ == "__main__", wie in zirkulären Importproblemen zu sehen

Es gibt ein zirkuläres Importproblem. Zum Beispiel

hoge.py


# coding: utf-8

import piyo

class Base:
	pass

class Hoge(Base):
	pass

Wann,

piyo.py


# coding: utf-8

import hoge

class Piyo(hoge.Base):
	pass

Wenn Sie zwei Python-Skripte haben, verursacht " python3 hoge.py "keinen Fehler, aber wenn Sie" python3 piyo.py" ausführen,

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 wird so auftreten. (Jetzt schaut er höflich "höchstwahrscheinlich aufgrund eines zirkulären Imports") Andererseits besteht eine Lösung darin, die Base-Klasse zu einem separaten Skript zu machen und dieses Skript aus beiden hoge.py / piyo.py zu importieren.

Übrigens, wenn ein solches Problem gelegentlich auf der Q & A-Website auftritt, ist die Antwort möglicherweise dieselbe wie oben, aber tatsächlich ist die Ursache der Ausnahme ziemlich tief und immer "Hmm. Ich war besorgt, und als ich den Grund verstand, dachte ich: "Oh, das ist der, um den ich mir vorher Sorgen gemacht habe. Wir sehen uns wieder." Heute werde ich das notieren.


Hier sind die Python-Spezifikationen, die Sie kennen müssen, um die Ursache dieses Problems zu verstehen.

Lassen Sie uns vor diesem Hintergrund überprüfen, was passiert, wenn wir die vorherige " python3 piyo.py "ausführen.

  1. In " piyo.py "werden" import hoge" und hoge.py importiert. Zu diesem Zeitpunkt ist die Klasse "Piyo" noch nicht definiert.
  2. In der importierten " hoge.py "wird" import piyo" ausgeführt, aber da " piyo.py "bereits geladen ist, wird nichts unternommen.
  3. Die nach " hoge.py "geschriebenen" Base "-Klassen und" Hoge "-Klassen sind definiert.

Auf diese Weise läuft es ohne Probleme ... das? Etwas ist anders.

Lassen Sie uns nun " python3 hoge.py "ausführen.

  1. In " hoge.py "werden" import piyo" und piyo.py importiert. Zu diesem Zeitpunkt sind die Klassen "Base" und "Hoge" undefiniert.
  2. In der importierten Datei " piyo.py "wird" import hoge" ausgeführt, aber da " hoge.py "bereits geladen ist, wird nichts unternommen.
  3. Verweisen Sie auf die Klasse "hoge.Base" als Quellklasse für die Klasse "Piyo". Da die Definition der Klasse "Base" jedoch nicht in "hoge.py" ausgeführt wird, wird das Modul "hoge" verwendet Es gibt keine "Basis" in einem Attribut und Sie erhalten eine "AttributeError" -Ausnahme.

Auf diese Weise tritt ein Fehler auf ... das?

Wenn Sie auf diese Weise die Ursache finden, ist dies das Gegenteil der tatsächlichen Operation. Ich habe hier immer ein Problem, aber ich erinnere mich an eine andere Python-Spezifikation und löse sie.

Lassen Sie uns auf dieser Grundlage die Funktion von " python3 piyo.py "erneut überprüfen.

  1. In " piyo.py "werden" import hoge" und hoge.py importiert. Zu diesem Zeitpunkt ist die Klasse "Piyo" noch nicht definiert.
  2. In der importierten " hoge.py "wird" import piyo" ausgeführt. " Piyo.py "ist bereits geladen, aber es ist ** der Modulname ist" __main__" ** und das Modul " piyo "ist nicht geladen, also" piyo" erneut .py` "wird ausgeführt. Zu diesem Zeitpunkt werden die folgenden Klassen "Base" und "Hoge" nicht ausgeführt, sodass sie noch nicht definiert sind.
  3. In der importierten Datei " piyo.py "wird" import hoge" ausgeführt, aber da " hoge.py "bereits geladen ist, wird nichts unternommen.

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

('__main__', <module '__main__' from 'a/piyo.py'>)
('piyo', <module 'piyo' from '/path/to/a/piyo.py'>)

Sicher, Sie erhalten eine AttributeError -Ausnahme. Schauen wir uns als Test den Inhalt von sys.modules an. (Mit Ausnahme der erforderlichen, weggelassen) Wie oben erwähnt, können Sie sehen, dass " piyo.py "zweimal gelesen wird. Lassen Sie uns nun einen Rückblick geben.

Grundsätzlich wird ein einmal importiertes Skript nicht zweimal ausgeführt, aber ein Skript, das beim Start ausgeführt wird, kann zweimal ausgeführt werden. Daher ist das Skript, das beim Start ausgeführt wird,

if __name__ == '__main__':
    main()

Sie sollten sich also Ihren Modulnamen ansehen und ihn nur beim ersten Mal ausführen.

Recommended Posts

Notwendigkeit für __name__ == "__main__", wie in zirkulären Importproblemen zu sehen
Notwendigkeit für __name__ == "__main__", wie in zirkulären Importproblemen zu sehen
Suchen Sie nach Zeichenfolgen in Dateien
Techniken zum Sortieren in Python
Über "für _ in range ():" von Python
Über die Notwendigkeit eines ersten Schrägstrichs im Abonnenten- und Herausgebernamen
Über die Notwendigkeit eines ersten Schrägstrichs im Abonnenten- und Herausgebernamen