2010-09-19 3 views
3

Мне просто интересно, почему __import__() дважды вызывает модуль __init__ при загрузке пакета.__import __() вызывает __init__.py дважды?

test.py 
testpkg/ 
     __init__.py 

test.py:

pkg = __import__("testpkg", fromlist=['']) 

__init__.py:

print "Called." 

После вызова python test.py, Called. будет распечатан дважды. Почему python дважды выполняет модуль «__init__»?

+0

Я не могу воспроизвести это поведение на Python 2.6.5. Какую версию вы используете? Вы уверены, что это полный код, который вы там разместили? –

+0

Я использую Python 2.6.4. Две строки кода - это все, что я использую для воспроизведения. Я только что попытался с Python 2.4.3, я получаю те же результаты. –

+0

Я получаю его на python 2.6.5 на linux2, построенном с g.c.c 4.4.3 – aaronasterling

ответ

5

Это ошибка Python. Передача нулевой строки в качестве элемента fromlist является незаконной и должна приводить к возникновению исключения.

Нет необходимости включать "" в fromlist; это неявно - сам модуль всегда загружается. Что на самом деле происходит, строка module.submodule использует пустую строку, в результате чего появляется имя модуля testpkg. с конечным периодом. Это импортируется буквально, и поскольку оно имеет другое имя, чем testpkg, оно импортируется как отдельный модуль.

Попробуйте это:

pkg = __import__("testpkg", fromlist=['']) 
import sys 
print sys["testpkg"] 
print sys["testpkg."] 

... и вы увидите дубликат модуля.

Кому-то, вероятно, следует подать билет на это, если его еще нет; слишком устал, чтобы сделать это сам прямо сейчас.

+0

Примечание: это происходит для меня в Python 2.6.4 и 3.1.1.Если вы делаете файл с ошибкой, убедитесь, что он еще не исправлен в новых версиях. –

+0

уже был билет 2090 для python 2.7, но я не видел никаких сообщений о версиях, упомянутых на этой странице, поэтому я добавил комментарий. – aaronasterling

+0

Вы правы. После замены [''] пустым списком модуль '__init__' вызывается только один раз. Просто исправил SO-Answer, с которого я скопировал этот код. –

5

Использование html-кода для импорта определенного модуля явно недоверчиво python-dev. Хотя это было filed as an issue, вероятность его фиксации низкая, потому что это рассматривается как неправильное использование fromlist для начала, а не обязательно для ошибки, и доступно лучшее решение.

То, что вы должны делать это с помощью importlib.import_module (доступен в стандартной библиотеке Python 2.7 и Python 3.1, или из PyPI с совместимостью обратно в Python 2.3 наряду с включения в Django 1.1, так как django.utils.importlib). Это предотвратит эту проблему, обеспечит лучший программный интерфейс для импорта модулей и даже позволит вам использовать относительный импорт при указании импортируемого вами пакета.

Если вы действительно не можете использовать importlib (например, PyPi зависимости не допускается, даже если код, который вы можете свободно копировать благодаря лицензии ФСФА и быть довольно короткими), то вы должны делать __import__("some.module"); mod = sys.modules["some.module"]. Это официальное, санкционированное решение python-dev проблемы (но только после вы не можете использовать importlib).

Смежные вопросы