Оптимизирует ли python модули при импорте несколько раз?
Если большой модуль загружен некоторым подмодулем вашего кода, есть ли какая-либо польза для ссылки на модуль из этого пространства имен вместо его повторного импорта?
Например:
У меня есть модуль MyLib, который широко использует ReallyBigLib. Если у меня есть код, который импортирует MyLib, я должен выкопать модуль так:
import MyLib
ReallyBigLib = MyLib.SomeModule.ReallyBigLib
или просто
import MyLib
import ReallyBigLib
Ответы
Ответ 1
Модули Python можно рассматривать как синглеты... независимо от того, сколько раз вы их импортируете, они инициализируются только один раз, поэтому лучше делать:
import MyLib
import ReallyBigLib
Соответствующая документация по оператору импорта:
https://docs.python.org/2/reference/simple_stmts.html#the-import-statement
Как только имя модуля известно (если не указано иное, термин "модуль" относится к обоим пакетам и модулям), может начаться поиск модуля или пакета. Первое место - это sys.modules, кеш всех модулей, которые были импортированы ранее. Если модуль найден там, он используется на этапе (2) импорта.
Импортированные модули кэшируются в sys.modules:
Это словарь, который отображает имена модулей в уже загруженные модули. Это можно манипулировать, чтобы принудительно перезагрузить модули и другие трюки. Обратите внимание, что удаление модуля из этого словаря не совпадает с вызовом reload() для соответствующего объекта модуля.
Ответ 2
Как указывали другие, Python поддерживает внутренний список всех импортированных модулей. Когда вы импортируете модуль в первый раз, модуль (a script) выполняется в своем собственном пространстве имен до конца, внутренний список обновляется, а выполнение продолжается после оператора импорта.
Попробуйте этот код:
# module/file a.py
print "Hello from a.py!"
import b
# module/file b.py
print "Hello from b.py!"
import a
Нет цикла: существует только поиск кэша.
>>> import b
Hello from b.py!
Hello from a.py!
>>> import a
>>>
Одна из красот Python заключается в том, как все переходит к выполнению script в пространстве имен.
Ответ 3
Это не имеет существенного значения. Если большой модуль уже загружен, второй импорт во втором примере ничего не делает, кроме добавления "ReallyBigLib" в текущее пространство имен.
Ответ 4
ПРЕДУПРЕЖДЕНИЕ: Python не гарантирует, что модуль не будет инициализирован дважды.
Я столкнулся с такой проблемой. См. Обсуждение:
http://code.djangoproject.com/ticket/8193
Ответ 5
Внутренний реестр импортируемых модулей - это словарь sys.modules
, который сопоставляет имена модулей объектам модуля. Вы можете посмотреть там, чтобы просмотреть все модули, которые в настоящее время импортированы.
Вы также можете вытащить некоторые полезные трюки (если вам нужно) путем обезглавливания с помощью sys.modules
- например, добавление ваших собственных объектов в виде псевдомодулей, которые могут быть импортированы другими модулями.
Ответ 6
Это то же самое по производительности. В Python пока нет компилятора JIT.