imp — Получите доступ к import внутренним компонентам

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

Утратил актуальность с версии 3.4, будет удален в версии 3.12: Модуль imp устарел в пользу importlib.


Этот модуль предоставляет интерфейс к механизмам, используемым для реализации инструкции import. Он определяет следующие константы и функции:

imp.get_magic()

Возвращает значение magic string, используемое для распознавания файлов кода, скомпилированного в байты (.pyc files). (Это значение может отличаться для каждой версии Python).

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

imp.get_suffixes()

Возвращает список кортежей из 3 элементов, каждый из которых описывает определенный тип модуля. Каждая тройка имеет вид (suffix, mode, type), где суффикс - это строка, которая добавляется к имени модуля для формирования имени файла для поиска, mode - это строка режима, которую нужно передать встроенной функции open() для открытия файла. файл (это может быть 'r' для текстовых файлов или 'rb' для двоичных файлов), а type - это тип файла, который имеет одно из значений PY_SOURCE, PY_COMPILED, или C_EXTENSION, описанных ниже.

Не рекомендуется, начиная с версии 3.3: Вместо этого используйте константы, определенные в importlib.machinery.

imp.find_module(name[, path])

Попробуйте найти название модуля. Если значение path опущено или None, выполняется поиск по списку имен каталогов, заданных sys.path, но сначала выполняется поиск в нескольких специальных местах: функция пытается найти встроенный модуль с заданным именем (C_BUILTIN), затем замороженный модуль (PY_FROZEN), и в некоторых системах также просматриваются некоторые другие места (в Windows он просматривается в реестре, который может указывать на определенный файл).

В противном случае path должен быть списком имен каталогов; в каждом каталоге выполняется поиск файлов с любым из указанных выше суффиксов, возвращаемых get_suffixes(). Недопустимые имена в списке автоматически игнорируются (но все элементы списка должны быть строками).

Если поиск завершен успешно, возвращаемое значение представляет собой кортеж из 3 элементов (file, pathname, description):

файл - это открытый file object, расположенный в начале, путь - это путь к найденному файлу, а описание - это кортеж из 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(), описывающий, какой тип модуля должен быть загружен.

Если загрузка прошла успешно, возвращаемым значением является объект module; в противном случае возникает исключение (обычно 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. Аргументом должен быть объект module, поэтому он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля с помощью внешнего редактора и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение - это объект module (то же, что и аргумент 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__, что приведет к оптимизации байт-кода.

путь необязательно должен существовать.

Изменено в версии 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)

Учитывая путь к имени файла PEP 3147, верните соответствующий путь к файлу с исходным кодом. Например, если путь равен /foo/bar/__pycache__/baz.cpython-32.pyc, возвращаемый путь будет /foo/bar/baz.py. путь необязательно должен существовать, однако, если он не соответствует формату 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.

Примеры

Следующая функция эмулирует стандартную инструкцию import до версии Python 1.4 (без иерархических имен модулей). (Эта реализация не будет работать в этой версии, поскольку find_module() был расширен, а load_module() был добавлен в версии 1.4.)

import imp
import sys

def __import__(name, globals=None, locals=None, fromlist=None):
    # Fast path: see if the module has already been imported.
    try:
        return sys.modules[name]
    except KeyError:
        pass

    # If any of the following calls raises an exception,
    # there's a problem we can't handle -- let the caller handle it.

    fp, pathname, description = imp.find_module(name)

    try:
        return imp.load_module(name, fp, pathname, description)
    finally:
        # Since we may exit via an exception, close fp explicitly.
        if fp:
            fp.close()
Вернуться на верх