Документация Python неофициальный перевод
Содержание страницы

36.2. imp – Доступ к внутренним механизмам importimp – Access the import internals

Исходный код: 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 равен 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(). Пример использования первого случая см. в разделе Примеры документации 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.

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()