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.
import
führt das Skript für dieses Modul aus.sys.modules
mit dem Modulnamen als Schlüssel gespeichert. Wenn sie ab dem zweiten Mal importiert werden, geben Sie einfach das in sys.modules
gespeicherte Objekt und das Modulskript zurück Die Verarbeitung wird niemals ausgeführt.Lassen Sie uns vor diesem Hintergrund überprüfen, was passiert, wenn wir die vorherige " python3 piyo.py
"ausführen.
piyo.py
"werden" import hoge
" und hoge.py
importiert. Zu diesem Zeitpunkt ist die Klasse "Piyo" noch nicht definiert. hoge.py
"wird" import piyo
" ausgeführt, aber da " piyo.py
"bereits geladen ist, wird nichts unternommen. 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.
hoge.py
"werden" import piyo
" und piyo.py
importiert. Zu diesem Zeitpunkt sind die Klassen "Base" und "Hoge" undefiniert. piyo.py
"wird" import hoge
" ausgeführt, aber da " hoge.py
"bereits geladen ist, wird nichts unternommen.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.
__main__
".Lassen Sie uns auf dieser Grundlage die Funktion von " python3 piyo.py
"erneut überprüfen.
piyo.py
"werden" import hoge
" und hoge.py
importiert. Zu diesem Zeitpunkt ist die Klasse "Piyo" noch nicht definiert. 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. 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