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

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

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


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

imp.get_magic()

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

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

imp.get_suffixes()

Возвращает список трехэлементных кортежей, каждый из которых описывает определенный тип модуля. Каждая тройка имеет вид (suffix, mode, type), где suffix - это строка, которая будет добавлена к имени модуля для формирования имени файла для поиска, mode - это строка 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() выше. Неверные имена в списке игнорируются (но все элементы списка должны быть строками).

В случае успешного поиска возвращаемым значением является трехэлементный кортеж (file, pathname, description):

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

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

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

Изменено в версии 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, возвращает путь к соответствующему файлу исходного кода. Например, если 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: Начиная с Python 3.3, используйте sys.implementation.cache_tag напрямую.

Следующие функции помогают взаимодействовать с внутренним механизмом блокировки системы импорта. Семантика блокировки импорта - это деталь реализации, которая может меняться от выпуска к выпуску. Однако 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):
    # 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()
Вернуться на верх