При написании модулей python существует ли способ запретить им дважды импортировать коды клиентов? Так же, как файлы заголовков c/С++:
#ifndef XXX
#define XXX
...
#endif
Большое спасибо!
При написании модулей python существует ли способ запретить им дважды импортировать коды клиентов? Так же, как файлы заголовков c/С++:
#ifndef XXX
#define XXX
...
#endif
Большое спасибо!
Модули 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
Импорт кэшируется и запускается только один раз. Дополнительный импорт ограничивает время поиска в sys.modules
.
Как указано в других ответах, 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 имеет единственный оператор import для a.py(import a
).
Выполнение /tmp/a.py приводит к следующему выводу:
[email protected]:/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
Поэтому лучше всего держать основной модуль достаточно минимальным и экспортировать большую часть его функциональных возможностей во внешний модуль, как рекомендовано здесь.
В этом ответе указаны еще два возможных сценария:
sys.path
, ведущие к одному и тому же модулю.