Как предотвратить двойной импорт модуля? - PullRequest
27 голосов
/ 08 января 2010

При написании модулей Python есть способ предотвратить его двойной импорт клиентскими кодами? Как и заголовочные файлы c / c ++:

#ifndef XXX
#define XXX
...
#endif

Большое спасибо!

Ответы [ 3 ]

38 голосов
/ 08 января 2010

Модули Python не импортируются несколько раз. Дважды запущенный импорт не перезагрузит модуль. Если вы хотите, чтобы он был перезагружен, вы должны использовать оператор reload. Вот демо

foo.py - модуль с одной строкой

print "I am being imported"

А вот экранная стенограмма нескольких попыток импорта.

   >>> import foo
   Hello, I am being imported
   >>> import foo # Will not print the statement
   >>> reload(foo) # Will print it again
   Hello, I am being imported
18 голосов
/ 08 января 2010

Импорт кэшируется и выполняется только один раз. Дополнительный импорт обойдется только в sys.modules.

.
13 голосов
/ 10 марта 2016

Как указано в других ответах, Python обычно не перезагружает модуль при обнаружении второго оператора импорта для него. Вместо этого он возвращает свою кэшированную версию из sys.modules без выполнения какого-либо кода.

Однако есть несколько подводных камней, на которые стоит обратить внимание:

  • При импорте основного модуля в качестве обычного модуля фактически создаются два экземпляра одного и того же модуля под разными именами.

    Это происходит потому, что во время запуска программы основной модуль настраивается с именем __main__. Таким образом, при импорте его как обычного модуля Python не обнаруживает его в sys.modules и импортирует его снова, но со своим собственным именем во второй раз.

    Рассмотрим файл / tmp / a.py со следующим содержимым:

    # /tmp/a.py
    import sys
    
    print "%s executing as %s, recognized as %s in sys.modules" % (__file__, __name__, sys.modules[__name__])
    import b
    

    Другой файл / tmp / b.py содержит единый оператор импорта для a.py (import a).
    Выполнение / tmp / a.py приводит к следующему выводу:

    root@machine:/tmp$ python a.py
    a.py executing as __main__, recognized as <module '__main__' from 'a.py'> in sys.modules
    /tmp/a.pyc executing as a, recognized as <module 'a' from '/tmp/a.pyc'> in sys.modules
    

    Поэтому лучше всего поддерживать основной модуль на минимальном уровне и экспортировать большую часть его функций во внешний модуль, как указано здесь .

  • Этот ответ указывает еще два возможных сценария:

    1. Немного разные операторы импорта, использующие разные записи в sys.path, ведущие к одному и тому же модулю.
    2. Попытка другого импорта модуля после того, как предыдущий не удался на полпути.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...