Ответ 1
Модули могут импортировать друг друга циклически, но есть улов. В простом случае он должен работать, перемещая операторы import
в нижнюю часть файла или не используя синтаксис from
.
Вот почему это работает:
При импорте модуля Python сначала проверяет sys.modules
. Если он там, он просто импортирует оттуда. Если он не существует, он пытается импортировать его обычным способом; в основном, он находит файл и запускает в нем материал.
Запуск модуля заполняет содержимое модуля. Например, скажем, у нас есть этот модуль, творчески названный example_opener
:
import webbrowser
def open_example():
webbrowser.open('http://www.example.com/')
В начале модуль пуст. Затем выполняется Python:
import webbrowser
После этого модуль содержит только webbrowser
. Затем Python выполняет следующее:
def open_example():
webbrowser.open('http://www.example.com/')
Python создает open_example
. Теперь модуль содержит webbrowser
и open_example
.
Скажите webbrowser
, содержащий этот код:
from example_opener import open_example
def open(url):
print url
Скажем, что example_opener
импортируется первым. Этот код выполняется:
import webbrowser
webbrowser
еще не импортирован, поэтому Python выполняет содержимое webbrowser
:
from example_opener import open_example
example_opener
был импортирован, но еще не полностью выполнен. Питону все равно. Python вытаскивает модуль из sys.modules
. На этом этапе example_opener
по-прежнему пуст. Он еще не определил open_example
и даже не выполнил импорт webbrowser
. Python не может найти open_example
в example_opener
, поэтому он терпит неудачу.
Что делать, если мы импортировали open_example
из конца webbrowser
и webbrowser
из конца example_opener
? Python начнет с выполнения этого кода:
def open_example():
webbrowser.open('http://www.example.com/')
webbrowser
еще не существует, но это не имеет значения до вызова open_example
. Теперь example_opener
содержит только open_example
. Затем он выполняет:
import webbrowser
Он еще не импортирован, поэтому Python выполняет webbrowser
. Он начинается:
def open(url):
print url
Он определяет open
. Затем он выполняет:
from example_opener import open_example
example_opener
находится в sys.modules
, поэтому он использует это. example_opener
содержит open_example
, поэтому он преуспевает. Python завершает импорт webbrowser
. Это завершает импорт webbrowser
из example_opener
. Это последнее в example_opener
, поэтому импорт example_opener
завершается, также успешно.