Модули импортированы дважды.Возможная ошибка в интерпретаторе Python - PullRequest
1 голос
/ 27 декабря 2011

Я разработал довольно хитрую схему импорта в своем проекте и думаю, что мог обнаружить ошибку в интерпретаторе Python, из-за которой модули импортируются дважды.

Вот как настроен мой тестовый проект:

  • /

    • Launcher.bat & mdash; Проект запускается отсюда. Он запускает 'main / __ init __. Py`, используя исполняемый файл Python 3.2

    • main / __ init __. Py & mdash; Скрипт __main__, запущенный 'Launcher.bat'

    • main / foo.py & mdash; Содержит пустой класс

    • external / __ init __. Py & mdash; Сценарий, внешний по отношению к «основным» сценариям проекта, используемый для демонстрации проблемы

. / Launcher.bat

@echo off
C:\Python32\python.exe main\__init__.py
pause

. / Главная / __ __ INIT. Ру

from foo import Foo
print("In 'main', Foo has id:", id(Foo))

# Add the directory from which 'Launcher.bat' was run,
# which is not the same as the './main' directory
# in which this script is located
import sys
sys.path.insert(1, '.')


# This script will try to import class Foo, but in doing so
# will casue the interpreter to import this './main/__init__.py'
# script a second time.
__import__('external')

. / Главная / foo.py

class Foo:
    pass

. / Внешний / __ __ INIT. Ру

from main.foo import Foo
print("In 'external', Foo has id:", id(Foo))

Все это напечатает сообщение 'Main script was imported' дважды. Если внешний скрипт импортирует любые другие скрипты, они тоже будут импортированы дважды. Я проверял это только на Python 3.2. Это ошибка или я ошибся?

Вывод программы:

В 'main' у Foo есть id: 12955136
В 'main' у Foo есть id: 12955136
Во «внешнем» Foo есть id: 12957456
Нажмите любую клавишу для продолжения . , ,

Ответы [ 2 ]

2 голосов
/ 27 декабря 2011

Я не думаю, что это ошибка.Вы должны спросить в списке python-dev более авторитетный ответ.Вы выполняете один раз (при запуске сценария) и импортируете один раз (из внешнего источника), поэтому строка печатается дважды.Это не импорт дважды.

Однако это ужасная настройка.Здесь много нарушений стиля.Разумеется, некоторые из них только для демонстрационных целей, это все еще довольно грязно.

  1. Вы не должны использовать файл пакета __init__.py в качестве файла, который должен быть запущен.Основной точкой входа должен быть скрипт, который импортирует пакет.
  2. У вас не должно быть импортированного модуля, импортирующего модуль, который его импортировал.Как и вы, внешний делает для главного.
1 голос
/ 27 декабря 2011

Первый print вводит в заблуждение: поскольку вы не импортируете, а выполняете файл в первый раз (__name__ == '__main__' верно), основные модули просто импортируются один раз. Переместите начальную точку во вторичный файл или проверьте на __name__ == '__main__'.

Кстати, циркуляр импорт - плохая идея. Вы должны разрешить циклический импорт (переместив foo в выделенную библиотеку). В качестве альтернативы вы можете сделать ваши модули реентерабельными (т.е. проверить, находится ли текущий каталог в sys.path перед его добавлением).

...