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

imp.md

176 строк · 21.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.2/library/imp.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 29.1. [`imp`](https://python-all.ru/3.2/library/imp.html#module-imp) – Доступ к внутренним механизмам [`импорта`](https://python-all.ru/3.2/reference/simple_stmts.html#import)89Этот модуль предоставляет интерфейс к механизмам, используемым для реализации оператора [`import`](https://python-all.ru/3.2/reference/simple_stmts.html#import). Он определяет следующие константы и функции:1011#### `imp.get_magic()`1213Возвращает магическое строковое значение, используемое для распознавания байт-кодовых файлов (файлов `.pyc`). (Это значение может различаться для разных версий Python.)1415#### `imp.get_suffixes()`1617Возвращает список трёхэлементных кортежей, каждый из которых описывает конкретный тип модуля. Каждая тройка имеет вид `(suffix, mode, type)`, где *suffix* – строка, добавляемая к имени модуля для формирования имени файла для поиска, *mode* – строка режима, передаваемая встроенной функции [`open()`](https://python-all.ru/3.2/library/functions.html#open) для открытия файла (это может быть `'r'` для текстовых файлов или `'rb'` для двоичных файлов), а *type* – тип файла, который принимает одно из значений [`PY_SOURCE`](https://python-all.ru/3.2/library/imp.html#imp.PY_SOURCE), [`PY_COMPILED`](https://python-all.ru/3.2/library/imp.html#imp.PY_COMPILED) или [`C_EXTENSION`](https://python-all.ru/3.2/library/imp.html#imp.C_EXTENSION), описанных ниже.1819#### `imp.find_module(name[, path])`2021Пытается найти модуль *name*. Если *path* опущен или равен `None`, выполняется поиск по списку имён каталогов, заданному `sys.path`, но сначала ищется в нескольких особых местах: функция пытается найти встроенный модуль с указанным именем ([`C_BUILTIN`](https://python-all.ru/3.2/library/imp.html#imp.C_BUILTIN)), затем замороженный модуль ([`PY_FROZEN`](https://python-all.ru/3.2/library/imp.html#imp.PY_FROZEN)), а в некоторых системах также проверяются и другие места (в Windows – реестр, который может указывать на конкретный файл).2223В противном случае *path* должен быть списком имён каталогов; в каждом каталоге выполняется поиск файлов с любым из суффиксов, возвращаемых [`get_suffixes()`](https://python-all.ru/3.2/library/imp.html#imp.get_suffixes) выше. Некорректные имена в списке молча игнорируются (но все элементы списка должны быть строками).2425Если поиск успешен, возвращаемое значение – трёхэлементный кортеж `(file, pathname, description)`:2627*file* – открытый [*файловый объект*](https://python-all.ru/3.2/glossary.html#term-file-object), позиционированный на начало; *pathname* – путь к найденному файлу; а *description* – трёхэлементный кортеж, как в списке, возвращаемом [`get_suffixes()`](https://python-all.ru/3.2/library/imp.html#imp.get_suffixes), описывающий тип найденного модуля.2829Если модуль не находится в файле, возвращаемый *file* равен `None`, *pathname* – пустая строка, а кортеж *description* содержит пустые строки для суффикса и режима; тип модуля указывается, как показано выше в скобках. Если поиск неуспешен, возбуждается [`ImportError`](https://python-all.ru/3.2/library/exceptions.html#ImportError). Другие исключения указывают на проблемы с аргументами или окружением.3031Если модуль является пакетом, *file* равен `None`, *pathname* – путь к пакету, а последним элементом кортежа *description* является [`PKG_DIRECTORY`](https://python-all.ru/3.2/library/imp.html#imp.PKG_DIRECTORY).3233Эта функция не работает с иерархическими именами модулей (именами, содержащими точки). Чтобы найти *P.M*, то есть подмодуль *M* пакета *P*, используйте [`find_module()`](https://python-all.ru/3.2/library/imp.html#imp.find_module) и [`load_module()`](https://python-all.ru/3.2/library/imp.html#imp.load_module) для поиска и загрузки пакета *P*, а затем используйте [`find_module()`](https://python-all.ru/3.2/library/imp.html#imp.find_module) с аргументом *path*, установленным в `P.__path__`. Если *P* сам имеет точечное имя, применяйте этот рецепт рекурсивно.3435#### `imp.load_module(name, file, pathname, description)`3637Загружает модуль, который ранее был найден с помощью [`find_module()`](https://python-all.ru/3.2/library/imp.html#imp.find_module) (или другого поиска, давшего совместимые результаты). Эта функция делает больше, чем просто импорт модуля: если модуль уже был импортирован, она перезагружает его! Аргумент *name* указывает полное имя модуля (включая имя пакета, если это подмодуль пакета). Аргумент *file* – это открытый файл, а *pathname* – соответствующее имя файла; они могут быть `None` и `''` соответственно, когда модуль является пакетом или не загружается из файла. Аргумент *description* – это кортеж, такой, какой вернула бы [`get_suffixes()`](https://python-all.ru/3.2/library/imp.html#imp.get_suffixes), описывающий, какой тип модуля должен быть загружен.3839Если загрузка успешна, возвращается объект модуля; в противном случае возбуждается исключение (обычно [`ImportError`](https://python-all.ru/3.2/library/exceptions.html#ImportError)).4041**Важно:** вызывающий код отвечает за закрытие аргумента *file*, если он не был `None`, даже при возбуждении исключения. Лучше всего это делать с помощью оператора [`try`](https://python-all.ru/3.2/reference/compound_stmts.html#try) ... [`finally`](https://python-all.ru/3.2/reference/compound_stmts.html#finally).4243#### `imp.new_module(name)`4445Возвращает новый пустой объект модуля с именем *name*. Этот объект *не* вставляется в `sys.modules`.4647#### `imp.lock_held()`4849Возвращает `True`, если блокировка импорта в данный момент удерживается, иначе `False`. На платформах без потоков всегда возвращает `False`.5051На платформах с потоками поток, выполняющий импорт, удерживает внутреннюю блокировку до завершения импорта. Эта блокировка не позволяет другим потокам выполнять импорт, пока исходный импорт не завершится, что, в свою очередь, предотвращает ситуацию, когда другие потоки могут увидеть незавершённые объекты модулей, созданные исходным потоком в процессе завершения его импорта (а также импортов, если таковые были, которые были вызваны этим).5253#### `imp.acquire_lock()`5455Захватывает блокировку импорта интерпретатора для текущего потока. Эта блокировка должна использоваться хуками импорта для обеспечения потокобезопасности при импорте модулей.5657После того как поток захватил блокировку импорта, тот же поток может захватить её снова без блокировки; поток должен освобождать её один раз за каждый захват.5859На платформах без потоков эта функция ничего не делает.6061#### `imp.release_lock()`6263Освобождает блокировку импорта интерпретатора. На платформах без потоков эта функция ничего не делает.6465#### `imp.reload(module)`6667Перезагружает ранее импортированный модуль *module*. Аргумент должен быть объектом модуля, то есть он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля во внешнем редакторе и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение – объект модуля (тот же, что и аргумент *module*).6869При выполнении `reload(module)`:7071- Код модулей Python перекомпилируется, и код уровня модуля выполняется заново, определяя новый набор объектов, которые привязываются к именам в словаре модуля. Функция `init` модулей расширения не вызывается второй раз.72- Как и в случае со всеми другими объектами в Python, старые объекты освобождаются только после того, как их счётчики ссылок упадут до нуля.73- Имена в пространстве имён модуля обновляются, чтобы указывать на любые новые или изменённые объекты.74- Другие ссылки на старые объекты (например, имена вне модуля) не перепривязываются для указания на новые объекты и должны быть обновлены в каждом пространстве имён, где они встречаются, если это необходимо.7576Существует ряд других предостережений:7778Если модуль синтаксически корректен, но его инициализация завершается ошибкой, первый оператор [`import`](https://python-all.ru/3.2/reference/simple_stmts.html#import) для него не связывает имя локально, но сохраняет (частично инициализированный) объект модуля в `sys.modules`. Чтобы перезагрузить модуль, сначала нужно снова выполнить [`import`](https://python-all.ru/3.2/reference/simple_stmts.html#import) (это свяжет имя с частично инициализированным объектом модуля), и только затем можно вызвать для него [`reload()`](https://python-all.ru/3.2/library/imp.html#imp.reload).7980При перезагрузке модуля его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имён заменяют старые определения, так что обычно это не проблема. Если новая версия модуля не определяет имя, которое было определено в старой версии, старое определение остаётся. Эту возможность можно использовать в пользу модуля, если он поддерживает глобальную таблицу или кеш объектов – с помощью оператора [`try`](https://python-all.ru/3.2/reference/compound_stmts.html#try) он может проверить наличие таблицы и, если нужно, пропустить её инициализацию:8182```python83try:84    cache85except NameError:86    cache = {}87```8889Перезагрузка встроенных или динамически загружаемых модулей допустима, но обычно не очень полезна, за исключением [`sys`](https://python-all.ru/3.2/library/sys.html#module-sys), [`__main__`](https://python-all.ru/3.2/library/__main__.html#module-__main__) и `__builtin__`. Однако во многих случаях модули расширения не рассчитаны на инициализацию более одного раза и могут произвольно завершаться ошибкой при перезагрузке.9091Если модуль импортирует объекты из другого модуля с помощью [`from`](https://python-all.ru/3.2/reference/simple_stmts.html#from) ... [`import`](https://python-all.ru/3.2/reference/simple_stmts.html#import) ..., то вызов [`reload()`](https://python-all.ru/3.2/library/imp.html#imp.reload) для другого модуля не переопределяет импортированные из него объекты. Один из способов обойти это – повторно выполнить оператор [`from`](https://python-all.ru/3.2/reference/simple_stmts.html#from), другой – использовать [`import`](https://python-all.ru/3.2/reference/simple_stmts.html#import) и квалифицированные имена (*module*.\*name\*).9293Если модуль создаёт экземпляры класса, перезагрузка модуля, определяющего класс, не влияет на определения методов экземпляров – они продолжают использовать старое определение класса. То же самое верно для производных классов.9495Следующие функции предоставляют удобные средства для работы с путями к [**PEP 3147**](https://python-all.ru/3.2/library/imp.html) скомпилированным в байт-код файлам.9697Новое в версии 3.2.9899#### `imp.cache_from_source(path, debug_override=None)`100101Возвращает путь [**PEP 3147**](https://python-all.ru/3.2/library/imp.html) к байт-кодовому файлу, связанному с исходным *path*. Например, если *path* равен `/foo/bar/baz.py`, возвращаемое значение будет `/foo/bar/__pycache__/baz.cpython-32.pyc` для Python 3.2. Строка `cpython-32` берётся из текущего magic-тега (см. [`get_tag()`](https://python-all.ru/3.2/library/imp.html#imp.get_tag)). Возвращаемый путь будет заканчиваться на `.pyc`, когда `__debug__` равно True, или на `.pyo` для оптимизированного Python (т.е. `__debug__` равно False). Передавая True или False для *debug\_override*, можно переопределить системное значение `__debug__` для выбора расширения.102103*path* не обязан существовать.104105#### `imp.source_from_cache(path)`106107По заданному *path* к имени файла [**PEP 3147**](https://python-all.ru/3.2/library/imp.html) возвращает путь к соответствующему исходному файлу. Например, если *path* равен `/foo/bar/__pycache__/baz.cpython-32.pyc`, возвращаемый путь будет `/foo/bar/baz.py`. *path* не обязан существовать, однако если он не соответствует формату [**PEP 3147**](https://python-all.ru/3.2/library/imp.html), возбуждается `ValueError`.108109#### `imp.get_tag()`110111Возвращает строку magic-тега в формате [**PEP 3147**](https://python-all.ru/3.2/library/imp.html), соответствующую magic-числу данной версии Python, как возвращается [`get_magic()`](https://python-all.ru/3.2/library/imp.html#imp.get_magic).112113Следующие константы с целочисленными значениями, определённые в этом модуле, используются для указания результата поиска [`find_module()`](https://python-all.ru/3.2/library/imp.html#imp.find_module).114115#### `imp.PY_SOURCE`116117Модуль найден как исходный файл.118119#### `imp.PY_COMPILED`120121Модуль найден как файл скомпилированного кода.122123#### `imp.C_EXTENSION`124125Модуль найден как динамически загружаемая общая библиотека.126127#### `imp.PKG_DIRECTORY`128129Модуль найден как каталог пакета.130131#### `imp.C_BUILTIN`132133Модуль найден как встроенный модуль.134135#### `imp.PY_FROZEN`136137Модуль найден как замороженный модуль.138139#### `class imp.NullImporter(path_string)`140141Тип [`NullImporter`](https://python-all.ru/3.2/library/imp.html#imp.NullImporter) – это хук импорта по [**PEP 302**](https://python-all.ru/3.2/library/imp.html), который обрабатывает строки пути, не являющиеся каталогами, возвращая отказ в поиске любых модулей. Вызов этого типа с существующим каталогом или пустой строкой возбуждает [`ImportError`](https://python-all.ru/3.2/library/exceptions.html#ImportError). В противном случае возвращается экземпляр [`NullImporter`](https://python-all.ru/3.2/library/imp.html#imp.NullImporter).142143Python добавляет экземпляры этого типа в `sys.path_importer_cache` для любых записей пути, которые не являются каталогами и не обрабатываются никакими другими хуками пути из `sys.path_hooks`. Экземпляры имеют только один метод:144145#### `find_module(fullname[, path])`146147Этот метод всегда возвращает `None`, указывая, что запрошенный модуль не найден.148149## 29.1.1. Примеры150151Следующая функция эмулирует то, что было стандартным оператором импорта до Python 1.4 (без иерархических имён модулей). (Эта *реализация* не работала бы в той версии, поскольку [`find_module()`](https://python-all.ru/3.2/library/imp.html#imp.find_module) была расширена, а [`load_module()`](https://python-all.ru/3.2/library/imp.html#imp.load_module) добавлена в версии 1.4.)152153```python154import imp155import sys156157def __import__(name, globals=None, locals=None, fromlist=None):158    # Быстрый путь: проверить, импортирован ли модуль ранее.159    try:160        return sys.modules[name]161    except KeyError:162        pass163164    # Если любой из следующих вызовов вызывает исключение,165    # возникает проблема, которую мы не можем обработать – пусть вызывающий код обработает её.166167    fp, pathname, description = imp.find_module(name)168169    try:170        return imp.load_module(name, fp, pathname, description)171    finally:172        # Так как возможен выход через исключение, необходимо явно закрыть fp.173        if fp:174            fp.close()175```176