Подтвердить что ты не робот

Два модуля Python требуют друг друга - может ли это работать?

У меня есть модуль веб-сервера Bottle со следующей строкой:

from foobar.formtools import auto_process_form_insert

И модуль foobar.formtools содержит эту строку:

from foobar.webserver import redirect, redirect_back

Конечно, оба результата приводят к следующим ошибкам (соответственно):

ImportError: невозможно импортировать имя auto_process_form_insert
ImportError: не может импортировать перенаправление имен

Это просто факт, что в Python два модуля не могут импортировать друг друга, и все импортируемые модули должны быть иерархическими по своему характеру, или я делаю что-то неправильно? Альтернативно, существует ли обходное решение, не позволяющее размещать все эти красивые функции в новых модулях?

4b9b3361

Ответ 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 завершается, также успешно.

Ответ 2

Не выполняйте from ... import .... Просто выполните import ... и ссылайтесь на его объекты, используя имя модуля.