Содержание страницы
36.2. imp – Доступ к внутренним механизмам импорта¶imp – Access the import internals
Исходный код: Lib/imp.py
Этот модуль предоставляет интерфейс к механизмам, используемым для реализации оператора
import. Он определяет следующие константы и функции:
-
imp.get_magic()¶ Возвращает строку магического значения, используемую для распознавания файлов с байт-кодом (файлы
.pyc). (Это значение может отличаться для разных версий Python.)Устарело с версии 3.4: Вместо этого используйте
importlib.util.MAGIC_NUMBER.
-
imp.get_suffixes()¶ Возвращает список кортежей из 3 элементов, каждый из которых описывает определённый тип модуля. Каждый кортеж имеет вид
(suffix, mode, type), где suffix – это строка, добавляемая к имени модуля для получения имени файла для поиска, mode – строка режима, передаваемая встроенной функцииopen()для открытия файла (это может быть'r'для текстовых файлов или'rb'для двоичных файлов), а type – тип файла, который может принимать одно из значенийPY_SOURCE,PY_COMPILEDилиC_EXTENSION, описанных ниже.Устарело с версии 3.3: Используйте константы, определённые в
importlib.machinery.
-
imp.find_module(name[, path])¶ Пытается найти модуль name. Если path опущен или
None, выполняется поиск по списку имён каталогов, указанному вsys.path, но сначала проверяется несколько особых мест: функция пытается найти встроенный модуль с заданным именем (C_BUILTIN), затем замороженный модуль (PY_FROZEN), а на некоторых системах также проверяются другие места (в Windows выполняется поиск в реестре, который может указывать на конкретный файл).В противном случае path должен быть списком имён каталогов; каждый каталог проверяется на наличие файлов с любым из суффиксов, возвращаемых
get_suffixes()выше. Недопустимые имена в списке игнорируются (но все элементы списка должны быть строками).Если поиск успешен, возвращаемое значение – кортеж из 3 элементов
(file, pathname, description):file – это открытый файловый объект, установленный в начало, pathname – путь к найденному файлу, а description – кортеж из 3 элементов, как в списке, возвращаемом
get_suffixes(), описывающий тип найденного модуля.Если модуль не находится в файле, возвращаемый file равен
None, pathname – пустая строка, а кортеж description содержит пустые строки для его suffix и mode; тип модуля указывается так, как приведено в скобках выше. Если поиск неуспешен, возбуждаетсяImportError. Другие исключения указывают на проблемы с аргументами или окружением.Если модуль является пакетом, file равен
None, pathname – это путь к пакету, а последний элемент кортежа description равенPKG_DIRECTORY.Эта функция не обрабатывает иерархические имена модулей (имена, содержащие точки). Чтобы найти P.M, то есть подмодуль M пакета P, используйте
find_module()иload_module()для поиска и загрузки пакета P, а затем используйтеfind_module()с аргументом path, установленным вP.__path__. Когда P сам имеет составное имя, применяйте этот рецепт рекурсивно.Устарело с версии 3.3: Используйте
importlib.util.find_spec(), если не требуется совместимость с Python 3.3; в этом случае используйтеimportlib.find_loader().
-
imp.load_module(name, file, pathname, description)¶ Загружает модуль, который был ранее найден с помощью
find_module()(или при другом поиске, давшем совместимые результаты). Эта функция делает больше, чем просто импорт модуля: если модуль уже был импортирован, она перезагружает его! Аргумент name указывает полное имя модуля (включая имя пакета, если это подмодуль пакета). Аргумент file – это открытый файл, а pathname – соответствующее имя файла; они могут бытьNoneи'', соответственно, когда модуль является пакетом или не загружается из файла. Аргумент description – это кортеж, как возвращаемыйget_suffixes(), описывающий, какой тип модуля необходимо загрузить.Если загрузка успешна, возвращается объект модуля; в противном случае возбуждается исключение (обычно
ImportError).Важно: вызывающая сторона обязана закрыть аргумент file, если он не равен
None, даже при возникновении исключения. Это лучше всего сделать с помощью оператораtry…finally.Устарело с версии 3.3: Если ранее использовалось совместно с
imp.find_module(), то рассмотрите использованиеimportlib.import_module(), в противном случае используйте загрузчик возвращаемый заменой, выбранной дляimp.find_module(). Если вы напрямую вызывалиimp.load_module()и связанные функции, используйте классы изimportlib.machinery, напримерimportlib.machinery.SourceFileLoader(name, path).load_module().
-
imp.new_module(name)¶ Возвращает новый пустой объект модуля с именем name. Этот объект не вставляется в
sys.modules.Устарело с версии 3.4: Вместо этого используйте
types.ModuleType.
-
imp.reload(module)¶ Перезагружает ранее импортированный модуль module. Аргумент должен быть объектом модуля, то есть он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля во внешнем редакторе и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение – объект модуля (тот же, что и аргумент module).
Когда выполняется
reload(module):- Код модулей Python перекомпилируется, и код уровня модуля выполняется заново,
определяя новый набор объектов, которые привязываются к именам в словаре модуля.
Функция
initмодулей расширения не вызывается второй раз. - Как и в случае со всеми другими объектами в Python, старые объекты освобождаются только после того, как их счётчики ссылок упадут до нуля.
- Имена в пространстве имён модуля обновляются, чтобы указывать на любые новые или изменённые объекты.
- Другие ссылки на старые объекты (например, имена вне модуля) не перепривязываются для указания на новые объекты и должны быть обновлены в каждом пространстве имён, где они встречаются, если это необходимо.
Существует ряд других предостережений:
При перезагрузке модуля его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имён заменяют старые определения, так что в целом это не проблема. Если новая версия модуля не определяет имя, которое было определено в старой версии, старое определение остаётся. Эта возможность может быть использована модулем с выгодой, если он поддерживает глобальную таблицу или кеш объектов – с помощью оператора
tryон может проверить наличие таблицы и пропустить её инициализацию при необходимости:try: cache except NameError: cache = {}
Перезагружать встроенные или динамически загружаемые модули допустимо, но обычно не очень полезно, за исключением
sys,__main__иbuiltins. Однако во многих случаях модули-расширения не рассчитаны на инициализацию более одного раза и могут отказывать в произвольных местах при перезагрузке.Если модуль импортирует объекты из другого модуля с помощью
from…import…, вызовreload()для другого модуля не переопределяет импортированные из него объекты – один из способов обойти это – повторно выполнить операторfrom, другой – использоватьimportи полные имена (module.*name*).Если модуль создаёт экземпляры класса, перезагрузка модуля, определяющего класс, не влияет на определения методов экземпляров – они продолжают использовать старое определение класса. То же самое верно для производных классов.
Изменено в версии 3.3: Требуется, чтобы в перезагружаемом модуле были определены как
__name__, так и__loader__, а не только__name__.Устарело с версии 3.4: Вместо этого используйте
importlib.reload().- Код модулей Python перекомпилируется, и код уровня модуля выполняется заново,
определяя новый набор объектов, которые привязываются к именам в словаре модуля.
Функция
Следующие функции предоставляют удобные средства для работы с путями к PEP 3147 скомпилированным в байт-код файлам.
Новое в версии 3.2.
-
imp.cache_from_source(path, debug_override=None)¶ Возвращает путь PEP 3147 к файлу со скомпилированным байт-кодом, связанному с исходным path. Например, если path равен
/foo/bar/baz.py, возвращаемое значение будет/foo/bar/__pycache__/baz.cpython-32.pycдля Python 3.2. Строкаcpython-32берётся из текущего магического тега (см.get_tag(); еслиsys.implementation.cache_tagне определён, будет возбужденоNotImplementedError). ПередаваяTrueилиFalseдля debug_override, вы можете переопределить значение системы для__debug__, что приведёт к оптимизированному байт-коду.path не обязан существовать.
Изменено в версии 3.3: Если
sys.implementation.cache_tagравноNone, то возбуждаетсяNotImplementedError.Устарело с версии 3.4: Вместо этого используйте
importlib.util.cache_from_source().Изменено в версии 3.5: Параметр debug_override больше не создаёт файл
.pyo.
-
imp.source_from_cache(path)¶ По path к имени файла PEP 3147 возвращает путь к соответствующему файлу исходного кода. Например, если path равен
/foo/bar/__pycache__/baz.cpython-32.pyc, возвращаемый путь будет/foo/bar/baz.py. path не обязан существовать, однако если он не соответствует формату PEP 3147, возбуждаетсяValueError. Еслиsys.implementation.cache_tagне определён, возбуждаетсяNotImplementedError.Изменено в версии 3.3: Возбуждает
NotImplementedError, когдаsys.implementation.cache_tagне определён.Устарело с версии 3.4: Вместо этого используйте
importlib.util.source_from_cache().
-
imp.get_tag()¶ Возвращает строку магического тега PEP 3147, соответствующую магическому числу этой версии Python, как возвращает
get_magic().Устарело с версии 3.4: Используйте
sys.implementation.cache_tagнапрямую, начиная с Python 3.3.
Следующие функции помогают взаимодействовать с внутренним механизмом блокировок системы импорта. Семантика блокировок импорта является деталью реализации, которая может меняться от версии к версии. Однако Python гарантирует, что циклические импорты работают без взаимных блокировок.
-
imp.lock_held()¶ Возвращает
True, если глобальная блокировка импорта в данный момент удерживается, иначеFalse. На платформах без потоков всегда возвращаетFalse.На платформах с потоками поток, выполняющий импорт, сначала удерживает глобальную блокировку импорта, затем устанавливает блокировку на каждый модуль для остальной части импорта. Это блокирует другие потоки от импорта того же модуля до завершения исходного импорта, предотвращая появление у других потоков неполных объектов модуля, созданных исходным потоком. Исключение делается для циклических импортов, которые по своей природе должны в какой-то момент предоставить неполный объект модуля.
Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.
Устарело с версии 3.4.
-
imp.acquire_lock()¶ Захватывает глобальную блокировку импорта интерпретатора для текущего потока. Эта блокировка должна использоваться хуками импорта для обеспечения потокобезопасности при импорте модулей.
После того как поток захватил блокировку импорта, тот же поток может захватить её снова без блокировки; поток должен освобождать её один раз за каждый захват.
На платформах без потоков эта функция ничего не делает.
Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.
Устарело с версии 3.4.
-
imp.release_lock()¶ Освобождает глобальную блокировку импорта интерпретатора. На платформах без поддержки потоков эта функция ничего не делает.
Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.
Устарело с версии 3.4.
Следующие константы с целочисленными значениями, определённые в этом модуле, используются для указания результата поиска find_module().
-
imp.PY_SOURCE¶ Модуль найден как исходный файл.
Устарело с версии 3.3.
-
imp.PY_COMPILED¶ Модуль найден как файл скомпилированного кода.
Устарело с версии 3.3.
-
imp.C_EXTENSION¶ Модуль найден как динамически загружаемая общая библиотека.
Устарело с версии 3.3.
-
imp.PKG_DIRECTORY¶ Модуль найден как каталог пакета.
Устарело с версии 3.3.
-
imp.C_BUILTIN¶ Модуль найден как встроенный модуль.
Устарело с версии 3.3.
-
imp.PY_FROZEN¶ Модуль найден как замороженный модуль.
Устарело с версии 3.3.
-
class
imp.NullImporter(path_string)¶ Тип
NullImporter– это хук импорта PEP 302, который обрабатывает строки пути, не являющиеся каталогами, и не находит ни одного модуля. Вызов этого типа с существующим каталогом или пустой строкой вызываетImportError. В противном случае возвращается экземплярNullImporter.Экземпляры имеют только один метод:
-
find_module(fullname[, path])¶ Этот метод всегда возвращает
None, указывая, что запрошенный модуль не найден.
Изменено в версии 3.3:
Noneвставляется вsys.path_importer_cacheвместо экземпляраNullImporter.Устарело с версии 3.4: Вместо этого вставляйте
Noneвsys.path_importer_cache.-
36.2.1. Примеры¶Examples
Следующая функция эмулирует то, что было стандартным оператором импорта до Python 1.4 (без иерархических имён модулей). (Эта реализация не работала бы в той версии, так как find_module() была расширена, а load_module() был добавлен в 1.4.)
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Быстрый путь: проверить, импортирован ли модуль ранее.
try:
return sys.modules[name]
except KeyError:
pass
# Если любой из следующих вызовов вызывает исключение,
# возникает проблема, которую мы не можем обработать – пусть вызывающий код обработает её.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Так как возможен выход через исключение, необходимо явно закрыть fp.
if fp:
fp.close()