При написании модулей 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, ведущие к одному и тому же модулю.