imp — Доступ к внутренностям import

Исходный код: Lib/imp.py

Не рекомендуется, начиная с версии 3.4: Модуль imp устарел в пользу importlib.


Модуль предоставляет интерфейс к механизмам используемых для реализации оператора 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 и pathname - и None и кортеж description, содержит пустой строки для его суффикса и режима; тип модуля указан в скобках выше. В случае неуспешного выполнения поиска возникает сообщение «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(). Например, использование бывшего случая, посмотрите раздел Примеры документации importlib.

imp.load_module(name, file, pathname, description)

Загрузить модуль, который был ранее найден find_module() (или иначе проводимым поиском, приводящим к совместимым результатам). Эта функция выполняет не только импорт модуля: если модуль уже был импортирован, он перезагрузит модуль! Аргумент name указывает полное имя модуля (включая имя пакета, если это подмодуль пакета). Аргумент file является открытым файлом, а pathname - соответствующим именем файла; они могут быть None и '' соответственно, когда модуль является пакетом или не загружается из файла. Аргумент description является кортежем, как и возвращенный get_suffixes(), описывающим, какой модуль должен быть загружен.

Если загрузка выполнена успешно, возвращает значение является объектом модуля; в противном случае возникает исключение (обычно ImportError).

Аргумент Важно: вызывающий отвечает за закрытие file, если он не был None, даже когда возникает исключение. Это лучше всего делать с помощью tryfinally инструкция.

Не рекомендуется, начиная с версии 3.3: Если ранее используемый в сочетании с imp.find_module(), то рассмотрите возможность использования importlib.import_module(), в противном случае используйте загрузчик возвращенный путем замены, выбранной для imp.find_module(). При вызове функций imp.load_module() и связанных функций непосредственно с аргументами пути к файлу используйте комбинацию importlib.util.spec_from_file_location() и importlib.util.module_from_spec(). Посмотрите раздел Примеры документации importlib для деталей различных подходов.

imp.new_module(name)

Возвращает новый пустой объект модуля с именем name. Этот объект не вставлен в sys.modules.

Не рекомендуется, начиная с версии 3.4: Используйте importlib.util.module_from_spec() вместо этого.

imp.reload(module)

Перезагрузите ранее импортированный module. Аргумент должен быть объектом модуля, поэтому он должен быть успешно импортирован ранее. Это полезно, если исходный файл модуля был отредактирован с помощью внешнего редактора и требуется опробовать новую версию без выхода из Python интерпретатор. Объект возвращает значение является объектом модуля (таким же, как аргумент module).

Когда reload(module) - выполняется:

  • Код модулей Python повторно собран, и уровень модуля код повторно выполнен, определив новый набор объектов, которые связаны с именами в словаре модуля. Функция init модулей расширения не вызывается второй раз.
  • Как и для всех других объектов в Python, старые объекты восстанавливаются только после того, как число привязок падает до нуля.
  • Имена в пространстве имен модулей обновляются для указания на новые или измененные объекты.
  • Другие ссылки на старые объекты (такие как имена, внешние по отношению к модулю) не являются повторными ссылками на новые объекты и должны обновляться в каждом пространстве имен, где они возникают, если это необходимо.

Есть и ряд других предостережений:

При перезагрузке модуля его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имен переопределят старые определения, поэтому это, как правило, не является проблемой. Если новая версия модуля не определяет имя, определенное старой версией, старое определение остается. Эта особенность может быть используемый к преимуществу модуля, если это поддерживает глобальный стол или кэш объектов — с try инструкция, это может проверить на присутствие стола и пропустить свою инициализацию при желании:

try:
    cache
except NameError:
    cache = {}

Легально, хотя, как правило, не очень полезно перезагружать встроенные или динамически загруженные модули, за исключением модулей sys, __main__ и builtins. Однако во многих случаях модули расширения не предназначены для инициализации более одного раза и могут отказывать произвольными способами при перезагрузке.

Если модуль импортирует объекты из другого модуля с помощью fromimport…, называя reload() для другого модуля не пересматривает объекты, импортированные из него —, один путь вокруг этого состоит в том, чтобы повторно выполнить from инструкция, другой должен использовать import и составные имена (module. name) вместо этого.

Если модуль иллюстрирует примерами сущности класса, перезагружая модуль, который определяет класс, не затрагивает определения метода сущности —, они продолжают использовать старое определение класса. То же самое относится и к производным классам.

Изменено в версии 3.3: Полагается и на __name__ и на __loader__, определяемый на модуле, перезагружаемом вместо просто __name__.

Не рекомендуется, начиная с версии 3.4: Используйте importlib.reload() вместо этого.

Следующие функции - удобства для обработки 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.

Примеры

Следующая функция подражает тому, что было стандартным импортом инструкция до 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()