również jako odniesienie wydaje się, że cykliczny import jest dozwolony w Pythonie 3.5 (i prawdopodobnie poza nim), ale nie 3.4 (i prawdopodobnie poniżej).
Charlie Parker
4
Korzystam z Pythona 3.7.2 i nadal mam błąd w czasie wykonywania z powodu zależności cyklicznych.
Richard Whitehead
Odpowiedzi:
280
W zeszłym roku odbyła się naprawdę dobra dyskusja na comp.lang.python . Dość dokładnie odpowiada na twoje pytanie.
Importowanie jest naprawdę bardzo proste. Pamiętaj tylko, że:
„import” i „from xxx import yyy” są instrukcjami wykonywalnymi. Wykonują się, gdy uruchomiony program osiągnie ten wiersz.
Jeśli modułu nie ma w sys.modules, wówczas import tworzy nowy wpis modułu w sys.modules, a następnie wykonuje kod w module. Nie zwraca kontroli do modułu wywołującego, dopóki wykonanie nie zostanie zakończone.
Jeśli moduł istnieje w sys.modules, wówczas import po prostu zwraca ten moduł, niezależnie od tego, czy zakończył wykonywanie. Dlatego cykliczny import może zwracać moduły, które wydają się częściowo puste.
Na koniec skrypt wykonujący działa w module o nazwie __main__, importowanie skryptu pod własną nazwą spowoduje utworzenie nowego modułu niezwiązanego z __main__.
Weź to wszystko razem i nie powinieneś mieć żadnych niespodzianek podczas importowania modułów.
@meawoppl Czy mógłbyś rozwinąć ten komentarz? Jak konkretnie się zmienili?
Dan Schien,
3
Na razie jedyne odniesienie do importu cyklicznego w python3 „Co nowego?” stron jest w wersji 3.5 . Napisano: „Obsługiwany jest teraz import okrągły związany z importem względnym”. @meawoppl znalazłeś coś jeszcze, czego nie ma na tych stronach?
zezollo 21.04.16
4
Oni są def. nieobsługiwany w 3.0-3.4. A przynajmniej semantyka sukcesu jest inna. Oto streszczenie, które znalazłem, nie wspominając o zmianach 3.5. gist.github.com/datagrok/40bf84d5870c41a77dc6
meawoppl
Proszę rozwinąć ten temat: „Na koniec skrypt wykonujący działa w module o nazwie main , importowanie skryptu pod własną nazwą spowoduje utworzenie nowego modułu niezwiązanego z main .”. Powiedzmy, że plik to a.py, a kiedy działa jako główny punkt wejścia, jest teraz głównym, jeśli ma kod jak z importu, jakaś zmienna. Czy ten sam plik „a.py” zostanie załadowany do tabeli modułów sys? Czy to oznacza, że jeśli powie napis print, będzie działał dwukrotnie? Raz dla głównego pliku i ponownie po napotkaniu importu?
zmienna
Ta odpowiedź ma 10 lat i chciałbym zmodernizować aktualizację, aby upewnić się, że pozostanie poprawna w różnych wersjach Pythona, 2.x lub 3.x
Fallenreaper,
296
Jeśli zrobisz to import foowewnątrz bari import barwewnątrz foo, będzie działać dobrze. Do czasu, gdy coś faktycznie się uruchomi, oba moduły zostaną w pełni załadowane i będą miały odniesienia do siebie.
Problem polega na tym, kiedy zamiast tego robisz from foo import abci from bar import xyz. Ponieważ teraz każdy moduł wymaga, aby drugi moduł został już zaimportowany (aby nazwa, którą importujemy, istniała), zanim będzie można ją zaimportować.
Wydaje się, że from foo import *i from bar import *również będzie działać dobrze.
Akavall,
1
Sprawdź edycję powyższego postu za pomocą a.py/b.py. Nie używa from x import y, a mimo to nadal pojawia się błąd importu cyklicznego
Greg Ennis
2
To nie do końca prawda. Podobnie jak w przypadku importowania * z, jeśli spróbujesz uzyskać dostęp do elementu w imporcie cyklicznym, na najwyższym poziomie, więc zanim skrypt zakończy wykonywanie, będziesz miał ten sam problem. Na przykład, jeśli ustawiasz pakiet globalny w jednym pakiecie z drugiego, a oba obejmują się nawzajem. Robiłem to, aby utworzyć niechlujną fabrykę dla obiektu w klasie bazowej, w którym ten obiekt mógłby być jedną z wielu podklas, a przy użyciu kodu nie trzeba było wiedzieć, który on faktycznie tworzy.
AaronM
3
@Akavall Nie bardzo. Spowoduje to jedynie zaimportowanie nazw dostępnych po wykonaniu importinstrukcji. Więc to nie spowoduje błędu, ale możesz nie uzyskać wszystkich oczekiwanych zmiennych.
sierpień
3
Uwaga: jeśli to zrobisz from foo import *i from bar import *wszystko wykonane w foojest w fazie inicjalizacji bar, a rzeczywiste funkcje w barnie zostały jeszcze zdefiniowane ...
Martian2049,
100
Cykliczne importowanie zostaje zakończone, ale należy uważać, aby nie używać cyklicznie importowanych modułów podczas inicjalizacji modułu.
Rozważ następujące pliki:
a.py:
print"a in"import sys
print"b imported: %s"%("b"in sys.modules,)import b
print"a out"
b.py:
print"b in"import a
print"b out"
x =3
Jeśli wykonasz a.py, otrzymasz:
$ python a.py
a in
b imported:False
b in
a in
b imported:True
a out
b out
a out
Podczas drugiego importu b.py (w drugim a in) interpreter Pythona nie importuje się bponownie, ponieważ już istnieje w module dict.
Jeśli próbujesz uzyskać dostęp b.xz apodczas inicjalizacji modułu dostaniesz AttributeError.
Dodaj następujący wiersz do a.py:
print b.x
Następnie dane wyjściowe to:
$ python a.py
a in
b imported:False
b in
a in
b imported:True
a out
Traceback(most recent call last):File"a.py", line 4,in<module>import b
File"/home/shlomme/tmp/x/b.py", line 2,in<module>import a
File"/home/shlomme/tmp/x/a.py", line 7,in<module>print b.x
AttributeError:'module' object has no attribute 'x'
Wynika to z faktu, że moduły są wykonywane podczas importu i w momencie b.xdostępu do niego linia x = 3nie została jeszcze wykonana, co nastąpi dopiero po b out.
to doskonale wyjaśnia problem, ale co z rozwiązaniem? jak możemy poprawnie importować i drukować x inne powyższe rozwiązanie nie działało dla mnie
mehmet
Myślę, że odpowiedź byłaby dużo zyskać, jeśli stosowany __name__zamiast 'a'. Na początku byłem całkowicie zdezorientowany, dlaczego plik zostanie wykonany dwukrotnie.
Bergi
30
Jak inne odpowiedzi opisują ten wzorzec jest akceptowalny w pythonie:
def dostuff(self):from foo import bar
...
Co pozwoli uniknąć wykonywania instrukcji importu, gdy plik zostanie zaimportowany przez inne moduły. Tylko jeśli istnieje logiczna zależność cykliczna, to się nie powiedzie.
Większość importów cyklicznych nie jest w rzeczywistości logicznymi importami cyklicznymi, ale powoduje ImportErrorbłędy, z powodu sposobu, w jaki import()wywoływane są instrukcje najwyższego poziomu całego pliku.
Te ImportErrorsmogą być prawie zawsze uniknąć, jeśli chcesz, aby import pozytywnie na górze :
Rozważ ten okrągły import:
Aplikacja A
# profiles/serializers.pyfrom images.serializers importSimplifiedImageSerializerclassSimplifiedProfileSerializer(serializers.Serializer):
name = serializers.CharField()classProfileSerializer(SimplifiedProfileSerializer):
recent_images =SimplifiedImageSerializer(many=True)
Aplikacja B
# images/serializers.pyfrom profiles.serializers importSimplifiedProfileSerializerclassSimplifiedImageSerializer(serializers.Serializer):
title = serializers.CharField()classImageSerializer(SimplifiedImageSerializer):
profile =SimplifiedProfileSerializer()
Błąd ImportError nie jest wywoływany, jeśli moduł został już zaimportowany. Moduły można importować dowolną liczbę razy, np. „Importuj a; importuj a” jest ok
Yuras
9
Mam tutaj przykład, który mnie uderzył!
foo.py
import bar
class gX(object):
g =10
bar.py
from foo import gX
o = gX()
main.py
import foo
import bar
print"all done"
W wierszu polecenia: $ python main.py
Traceback(most recent call last):File"m.py", line 1,in<module>import foo
File"/home/xolve/foo.py", line 1,in<module>import bar
File"/home/xolve/bar.py", line 1,in<module>from foo import gX
ImportError: cannot import name gX
Jak to naprawiłeś? Próbuję zrozumieć cykliczny import, aby rozwiązać mój własny problem, który wygląda bardzo podobnie do tego, co robisz ...
c089,
12
Errm ... Myślę, że naprawiłem swój problem z tym niesamowicie brzydkim hakiem. {{{jeśli nie „foo.bar” w sys.modules: z paska importu foo else: bar = sys.modules ['foo.bar']}}} Osobiście uważam, że okrągły import jest OGROMNYM znakiem ostrzegawczym na złym kodzie projekt ...
c089,
5
@ c089, czy można po prostu przenieść import barsię foo.pydo końcowego
warvariuc
5
Jeśli bari foooba muszą użyć gX, „najczystszym” rozwiązaniem jest umieszczenie gXinnego modułu, posiadanie obu fooi barimportowanie tego modułu. (najczystszy w tym sensie, że nie ma ukrytych zależności semantycznych).
Tim Wilder,
2
Tim ma rację. Zasadniczo to dlatego, że barnie można nawet znaleźć gXw foo. cykliczny import sam w sobie jest w porządku, ale po prostu gXnie jest definiowany podczas importowania.
Martian2049,
9
Moduł a.py:
import b
print("This is from module a")
Moduł b.py
import a
print("This is from module b")
Uruchomienie „modułu a” spowoduje:
>>>'This is from module a''This is from module b''This is from module a'>>>
Wyprowadza te 3 wiersze, podczas gdy miał generować nieskończoność z powodu importu cyklicznego. Co dzieje się linia po linii podczas uruchamiania „Modułu a” jest wymienione tutaj:
Pierwsza linia to import b. więc odwiedzi moduł b
Pierwsza linia w module b to import a. więc odwiedzi moduł a
Pierwsza linia w module a to, import bale pamiętaj, że ta linia nie będzie już więcej wykonywana , ponieważ każdy plik w pythonie wykonuje wiersz importu tylko raz, nie ma znaczenia, gdzie i kiedy jest wykonywany. więc przejdzie do następnej linii i wydrukuje "This is from module a".
Po zakończeniu wizyty w całym module a z modułu b nadal jesteśmy w module b. więc zostanie wydrukowany następny wiersz"This is from module b"
Linie modułu b są wykonywane całkowicie. więc wrócimy do modułu a, w którym uruchomiliśmy moduł b.
linia importu b została już wykonana i nie zostanie wykonana ponownie. zostanie wydrukowany następny wiersz "This is from module a"i program zostanie zakończony.
Całkowicie zgadzam się z odpowiedzią pytającego tutaj. Ale natknąłem się na kod, który był wadliwy przy okrągłym imporcie i powodował problemy podczas próby dodania testów jednostkowych. Aby szybko go załatać bez zmiany wszystkiego, możesz rozwiązać problem, wykonując import dynamiczny.
# Hack to import something without circular import issuedef load_module(name):"""Load module using imp.find_module"""
names = name.split(".")
path =Nonefor name in names:
f, path, info = imp.find_module(name, path)
path =[path]return imp.load_module(name, f, path[0], info)
constants = load_module("app.constants")
Ponownie, nie jest to stała poprawka, ale może pomóc komuś, kto chce naprawić błąd importu bez zmiany zbyt dużej części kodu.
Jest tu wiele świetnych odpowiedzi. Chociaż zwykle istnieją szybkie rozwiązania problemu, z których niektóre wydają się bardziej pytoniczne niż inne, jeśli masz luksus polegający na refaktoryzacji, innym podejściem jest analiza organizacji kodu i próba usunięcia zależności cyklicznej. Możesz na przykład stwierdzić, że masz:
Plik a.py
from b import B
class A:@staticmethoddef save_result(result):print('save the result')@staticmethoddef do_something_a_ish(param):
A.save_result(A.use_param_like_a_would(param))@staticmethoddef do_something_related_to_b(param):
B.do_something_b_ish(param)
Plik b.py
from a import A
class B:@staticmethoddef do_something_b_ish(param):
A.save_result(B.use_param_like_b_would(param))
W takim przypadku wystarczy przenieść jedną statyczną metodę do osobnego pliku, powiedz c.py:
Plik c.py
def save_result(result):print('save the result')
pozwoli na usunięcie save_resultmetody z A, a tym samym na usunięcie importu A z punktu b:
Plik refaktoryzowany a.py
from b import B
from c import save_result
class A:@staticmethoddef do_something_a_ish(param):
A.save_result(A.use_param_like_a_would(param))@staticmethoddef do_something_related_to_b(param):
B.do_something_b_ish(param)
Plik refaktoryzowany b.py
from c import save_result
class B:@staticmethoddef do_something_b_ish(param):
save_result(B.use_param_like_b_would(param))
Podsumowując, jeśli masz narzędzie (np. Pylint lub PyCharm), które informuje o metodach, które mogą być statyczne, samo nałożenie staticmethodna nie dekoratora może nie być najlepszym sposobem na wyciszenie ostrzeżenia. Mimo że metoda wydaje się powiązana z klasą, może być lepiej ją oddzielić, zwłaszcza jeśli masz kilka blisko powiązanych modułów, które mogą wymagać tej samej funkcjonalności i zamierzasz ćwiczyć zasady DRY.
Okrągły import może być mylący, ponieważ import ma dwie rzeczy:
wykonuje importowany kod modułu
dodaje importowany moduł do importowanej globalnej tabeli symboli
Pierwsze jest wykonywane tylko raz, a drugie przy każdym wyciągu z importu. Okrągły import tworzy sytuację, gdy moduł importujący używa importowanego z częściowo wykonanym kodem. W rezultacie nie zobaczy obiektów utworzonych po instrukcji importu. Poniżej pokazano przykładowy kod.
Okrągły import nie jest ostatecznym złem, którego należy unikać za wszelką cenę. W niektórych frameworkach, takich jak Flask, są one dość naturalne, a modyfikacja kodu w celu ich wyeliminowania nie poprawia kodu.
main.py
print'import b'import b
print'a in globals() {}'.format('a'in globals())print'import a'import a
print'a in globals() {}'.format('a'in globals())if __name__ =='__main__':print'imports done'print'b has y {}, a is b.a {}'.format(hasattr(b,'y'), a is b.a)
b.by
print"b in, __name__ = {}".format(__name__)
x =3print'b imports a'import a
y =5print"b out"
a.py
print'a in, __name__ = {}'.format(__name__)print'a imports b'import b
print'b has x {}'.format(hasattr(b,'x'))print'b has y {}'.format(hasattr(b,'y'))print"a out"
wyjście main.py python z komentarzami
import b
b in, __name__ = b # b code execution started
b imports a
a in, __name__ = a # a code execution started
a imports b # b code execution is already in progress
b has x True
b has y False# b defines y after a import,
a out
b out
a in globals()False# import only adds a to main global symbol table import a
a in globals()True
imports done
b has y True, a is b.a True# all b objects are available
Ok, myślę, że mam całkiem fajne rozwiązanie. Powiedzmy, że masz plik ai plik b. Masz deflub classw pliku b, który chcesz użyć w module a, ale trzeba coś innego, albo def, classlub zmienna z pliku a, który trzeba w swojej definicji lub klasy w pliku b. To, co możesz zrobić, to na dole pliku a, po wywołaniu funkcji lub klasy w pliku, aktóra jest potrzebna w pliku b, ale przed wywołaniem funkcji lub klasy z pliku b, które potrzebujesz do pliku a, powiedz import b
wtedy, a oto kluczowa część , we wszystkich definicjach lub klasach w pliku, bktóre wymagają pliku deflub classz plikua(nazwijmy to CLASS), mówiszfrom a import CLASS
Działa to, ponieważ można zaimportować plik bbez wykonywania przez Pythona żadnej z instrukcji importu w pliku b, a tym samym uniknąć importu cyklicznego.
Na przykład:
Plik a:
class A(object):def __init__(self, name):
self.name = name
CLASS = A("me")import b
go = B(6)
go.dostuff
Plik b:
class B(object):def __init__(self, number):
self.number = number
def dostuff(self):from a import CLASS
print"Hello "+ CLASS.name +", "+ str(number)+" is an interesting number."
from a import CLASStak naprawdę nie pomija wykonywania całego kodu w a.py. Oto, co się naprawdę dzieje: (1) Cały kod w pliku a.py jest uruchamiany jako specjalny moduł „__main__”. (2) W import bmomencie uruchamiany jest kod najwyższego poziomu w b.py (definiowanie klasy B), a następnie kontrola powraca do „__main__”. (3) „__main__” ostatecznie przekazuje kontrolę go.dostuff(). (4) kiedy DoStuff () przychodzi import a, to działa cały kod w a.py ponownie , tym razem jako modułu „a”; następnie importuje obiekt CLASS z nowego modułu „a”. Tak naprawdę działałoby to równie dobrze, gdybyś używał import agdziekolwiek w b.py.
Odpowiedzi:
W zeszłym roku odbyła się naprawdę dobra dyskusja na comp.lang.python . Dość dokładnie odpowiada na twoje pytanie.
źródło
Jeśli zrobisz to
import foo
wewnątrzbar
iimport bar
wewnątrzfoo
, będzie działać dobrze. Do czasu, gdy coś faktycznie się uruchomi, oba moduły zostaną w pełni załadowane i będą miały odniesienia do siebie.Problem polega na tym, kiedy zamiast tego robisz
from foo import abc
ifrom bar import xyz
. Ponieważ teraz każdy moduł wymaga, aby drugi moduł został już zaimportowany (aby nazwa, którą importujemy, istniała), zanim będzie można ją zaimportować.źródło
from foo import *
ifrom bar import *
również będzie działać dobrze.from x import y
, a mimo to nadal pojawia się błąd importu cyklicznegoimport
instrukcji. Więc to nie spowoduje błędu, ale możesz nie uzyskać wszystkich oczekiwanych zmiennych.from foo import *
ifrom bar import *
wszystko wykonane wfoo
jest w fazie inicjalizacjibar
, a rzeczywiste funkcje wbar
nie zostały jeszcze zdefiniowane ...Cykliczne importowanie zostaje zakończone, ale należy uważać, aby nie używać cyklicznie importowanych modułów podczas inicjalizacji modułu.
Rozważ następujące pliki:
a.py:
b.py:
Jeśli wykonasz a.py, otrzymasz:
Podczas drugiego importu b.py (w drugim
a in
) interpreter Pythona nie importuje sięb
ponownie, ponieważ już istnieje w module dict.Jeśli próbujesz uzyskać dostęp
b.x
za
podczas inicjalizacji modułu dostanieszAttributeError
.Dodaj następujący wiersz do
a.py
:Następnie dane wyjściowe to:
Wynika to z faktu, że moduły są wykonywane podczas importu i w momencie
b.x
dostępu do niego liniax = 3
nie została jeszcze wykonana, co nastąpi dopiero pob out
.źródło
__name__
zamiast'a'
. Na początku byłem całkowicie zdezorientowany, dlaczego plik zostanie wykonany dwukrotnie.Jak inne odpowiedzi opisują ten wzorzec jest akceptowalny w pythonie:
Co pozwoli uniknąć wykonywania instrukcji importu, gdy plik zostanie zaimportowany przez inne moduły. Tylko jeśli istnieje logiczna zależność cykliczna, to się nie powiedzie.
Większość importów cyklicznych nie jest w rzeczywistości logicznymi importami cyklicznymi, ale powoduje
ImportError
błędy, z powodu sposobu, w jakiimport()
wywoływane są instrukcje najwyższego poziomu całego pliku.Te
ImportErrors
mogą być prawie zawsze uniknąć, jeśli chcesz, aby import pozytywnie na górze :Rozważ ten okrągły import:
Aplikacja A
Aplikacja B
David Beazleys znakomita rozmowa Moduły i pakiety: Live and Let Die! - PyCon 2015 ,
1:54:00
oto sposób radzenia sobie z okrągłym importem w pythonie:Spróbuje zaimportować
SimplifiedImageSerializer
i jeśliImportError
zostanie podniesiony, ponieważ jest już zaimportowany, wyciągnie go z importcache.PS: Musisz przeczytać cały post głosem Davida Beazleya.
źródło
Mam tutaj przykład, który mnie uderzył!
foo.py
bar.py
main.py
W wierszu polecenia: $ python main.py
źródło
import bar
sięfoo.py
do końcowegobar
ifoo
oba muszą użyćgX
, „najczystszym” rozwiązaniem jest umieszczeniegX
innego modułu, posiadanie obufoo
ibar
importowanie tego modułu. (najczystszy w tym sensie, że nie ma ukrytych zależności semantycznych).bar
nie można nawet znaleźćgX
w foo. cykliczny import sam w sobie jest w porządku, ale po prostugX
nie jest definiowany podczas importowania.Moduł a.py:
Moduł b.py
Uruchomienie „modułu a” spowoduje:
Wyprowadza te 3 wiersze, podczas gdy miał generować nieskończoność z powodu importu cyklicznego. Co dzieje się linia po linii podczas uruchamiania „Modułu a” jest wymienione tutaj:
import b
. więc odwiedzi moduł bimport a
. więc odwiedzi moduł aimport b
ale pamiętaj, że ta linia nie będzie już więcej wykonywana , ponieważ każdy plik w pythonie wykonuje wiersz importu tylko raz, nie ma znaczenia, gdzie i kiedy jest wykonywany. więc przejdzie do następnej linii i wydrukuje"This is from module a"
."This is from module b"
"This is from module a"
i program zostanie zakończony.źródło
Całkowicie zgadzam się z odpowiedzią pytającego tutaj. Ale natknąłem się na kod, który był wadliwy przy okrągłym imporcie i powodował problemy podczas próby dodania testów jednostkowych. Aby szybko go załatać bez zmiany wszystkiego, możesz rozwiązać problem, wykonując import dynamiczny.
Ponownie, nie jest to stała poprawka, ale może pomóc komuś, kto chce naprawić błąd importu bez zmiany zbyt dużej części kodu.
Twoje zdrowie!
źródło
Jest tu wiele świetnych odpowiedzi. Chociaż zwykle istnieją szybkie rozwiązania problemu, z których niektóre wydają się bardziej pytoniczne niż inne, jeśli masz luksus polegający na refaktoryzacji, innym podejściem jest analiza organizacji kodu i próba usunięcia zależności cyklicznej. Możesz na przykład stwierdzić, że masz:
Plik a.py
Plik b.py
W takim przypadku wystarczy przenieść jedną statyczną metodę do osobnego pliku, powiedz
c.py
:Plik c.py
pozwoli na usunięcie
save_result
metody z A, a tym samym na usunięcie importu A z punktu b:Plik refaktoryzowany a.py
Plik refaktoryzowany b.py
Podsumowując, jeśli masz narzędzie (np. Pylint lub PyCharm), które informuje o metodach, które mogą być statyczne, samo nałożenie
staticmethod
na nie dekoratora może nie być najlepszym sposobem na wyciszenie ostrzeżenia. Mimo że metoda wydaje się powiązana z klasą, może być lepiej ją oddzielić, zwłaszcza jeśli masz kilka blisko powiązanych modułów, które mogą wymagać tej samej funkcjonalności i zamierzasz ćwiczyć zasady DRY.źródło
Okrągły import może być mylący, ponieważ import ma dwie rzeczy:
Pierwsze jest wykonywane tylko raz, a drugie przy każdym wyciągu z importu. Okrągły import tworzy sytuację, gdy moduł importujący używa importowanego z częściowo wykonanym kodem. W rezultacie nie zobaczy obiektów utworzonych po instrukcji importu. Poniżej pokazano przykładowy kod.
Okrągły import nie jest ostatecznym złem, którego należy unikać za wszelką cenę. W niektórych frameworkach, takich jak Flask, są one dość naturalne, a modyfikacja kodu w celu ich wyeliminowania nie poprawia kodu.
main.py
b.by
a.py
wyjście main.py python z komentarzami
źródło
Rozwiązałem problem w następujący sposób i działa dobrze bez żadnych błędów. Rozważ dwa pliki
a.py
ib.py
.Dodałem to
a.py
i zadziałało.a.py:
b.py:
Otrzymałem wynik
źródło
Ok, myślę, że mam całkiem fajne rozwiązanie. Powiedzmy, że masz plik
a
i plikb
. Maszdef
lubclass
w plikub
, który chcesz użyć w modulea
, ale trzeba coś innego, albodef
,class
lub zmienna z plikua
, który trzeba w swojej definicji lub klasy w plikub
. To, co możesz zrobić, to na dole plikua
, po wywołaniu funkcji lub klasy w pliku,a
która jest potrzebna w plikub
, ale przed wywołaniem funkcji lub klasy z plikub
, które potrzebujesz do plikua
, powiedzimport b
wtedy, a oto kluczowa część , we wszystkich definicjach lub klasach w pliku,b
które wymagają plikudef
lubclass
z plikua
(nazwijmy toCLASS
), mówiszfrom a import CLASS
Działa to, ponieważ można zaimportować plik
b
bez wykonywania przez Pythona żadnej z instrukcji importu w plikub
, a tym samym uniknąć importu cyklicznego.Na przykład:
Plik a:
Plik b:
Voila
źródło
from a import CLASS
tak naprawdę nie pomija wykonywania całego kodu w a.py. Oto, co się naprawdę dzieje: (1) Cały kod w pliku a.py jest uruchamiany jako specjalny moduł „__main__”. (2) Wimport b
momencie uruchamiany jest kod najwyższego poziomu w b.py (definiowanie klasy B), a następnie kontrola powraca do „__main__”. (3) „__main__” ostatecznie przekazuje kontrolęgo.dostuff()
. (4) kiedy DoStuff () przychodziimport a
, to działa cały kod w a.py ponownie , tym razem jako modułu „a”; następnie importuje obiekt CLASS z nowego modułu „a”. Tak naprawdę działałoby to równie dobrze, gdybyś używałimport a
gdziekolwiek w b.py.