imp.md
1> **Источник:** https://python-all.ru/3.10/library/imp.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`imp`](https://python-all.ru/3.10/library/imp.html#module-imp) – Доступ к внутренним механизмам [import](https://python-all.ru/3.10/reference/import.html#importsystem)89**Исходный код:** [Lib/imp.py](https://python-all.ru/src/3.10/Lib/imp.py)1011Устарело с версии 3.4: Модуль [`imp`](https://python-all.ru/3.10/library/imp.html#module-imp) устарел в пользу [`importlib`](https://python-all.ru/3.10/library/importlib.html#module-importlib).1213---1415Этот модуль предоставляет интерфейс к механизмам, используемым для реализации оператора [`import`](https://python-all.ru/3.10/reference/simple_stmts.html#import). Он определяет следующие константы и функции:1617#### `imp.get_magic()`1819Возвращает строку магического значения, используемую для распознавания файлов с байт-кодом (файлы `.pyc`). (Это значение может отличаться для разных версий Python.)2021Устарело с версии 3.4: Вместо этого используйте [`importlib.util.MAGIC_NUMBER`](https://python-all.ru/3.10/library/importlib.html#importlib.util.MAGIC_NUMBER).2223#### `imp.get_suffixes()`2425Возвращает список кортежей из 3 элементов, каждый из которых описывает определённый тип модуля. Каждый кортеж имеет вид `(suffix, mode, type)`, где *suffix* – это строка, добавляемая к имени модуля для получения имени файла для поиска, *mode* – строка режима, передаваемая встроенной функции [`open()`](https://python-all.ru/3.10/library/functions.html#open) для открытия файла (это может быть `'r'` для текстовых файлов или `'rb'` для двоичных файлов), а *type* – тип файла, который может принимать одно из значений [`PY_SOURCE`](https://python-all.ru/3.10/library/imp.html#imp.PY_SOURCE), [`PY_COMPILED`](https://python-all.ru/3.10/library/imp.html#imp.PY_COMPILED) или [`C_EXTENSION`](https://python-all.ru/3.10/library/imp.html#imp.C_EXTENSION), описанных ниже.2627Устарело с версии 3.3: Используйте константы, определённые в [`importlib.machinery`](https://python-all.ru/3.10/library/importlib.html#module-importlib.machinery).2829#### `imp.find_module(name[, path])`3031Пытается найти модуль *name*. Если *path* опущен или `None`, выполняется поиск по списку имён каталогов, указанному в `sys.path`, но сначала проверяется несколько особых мест: функция пытается найти встроенный модуль с заданным именем ([`C_BUILTIN`](https://python-all.ru/3.10/library/imp.html#imp.C_BUILTIN)), затем замороженный модуль ([`PY_FROZEN`](https://python-all.ru/3.10/library/imp.html#imp.PY_FROZEN)), а на некоторых системах также проверяются другие места (в Windows выполняется поиск в реестре, который может указывать на конкретный файл).3233В противном случае *path* должен быть списком имён каталогов; каждый каталог проверяется на наличие файлов с любым из суффиксов, возвращаемых [`get_suffixes()`](https://python-all.ru/3.10/library/imp.html#imp.get_suffixes) выше. Недопустимые имена в списке игнорируются (но все элементы списка должны быть строками).3435Если поиск успешен, возвращаемое значение – кортеж из 3 элементов `(file, pathname, description)`:3637*file* – это открытый [файловый объект](https://python-all.ru/3.10/glossary.html#term-file-object), установленный в начало, *pathname* – путь к найденному файлу, а *description* – кортеж из 3 элементов, как в списке, возвращаемом [`get_suffixes()`](https://python-all.ru/3.10/library/imp.html#imp.get_suffixes), описывающий тип найденного модуля.3839Если модуль встроенный или замороженный, то *file* и *pathname* оба равны `None`, а кортеж *description* содержит пустые строки для суффикса и режима; тип модуля указывается, как приведено в скобках выше. Если поиск неуспешен, возбуждается [`ImportError`](https://python-all.ru/3.10/library/exceptions.html#ImportError). Другие исключения указывают на проблемы с аргументами или окружением.4041Если модуль является пакетом, *file* равен `None`, *pathname* – это путь к пакету, а последний элемент кортежа *description* равен [`PKG_DIRECTORY`](https://python-all.ru/3.10/library/imp.html#imp.PKG_DIRECTORY).4243Эта функция не обрабатывает иерархические имена модулей (имена, содержащие точки). Чтобы найти *P.M*, то есть подмодуль *M* пакета *P*, используйте [`find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module) и [`load_module()`](https://python-all.ru/3.10/library/imp.html#imp.load_module) для поиска и загрузки пакета *P*, а затем используйте [`find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module) с аргументом *path*, установленным в `P.__path__`. Когда *P* сам имеет составное имя, применяйте этот рецепт рекурсивно.4445Устарело с версии 3.3: Вместо этого используйте [`importlib.util.find_spec()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.find_spec), если не требуется совместимость с Python 3.3; в таком случае используйте [`importlib.find_loader()`](https://python-all.ru/3.10/library/importlib.html#importlib.find_loader). Пример использования первого случая см. в разделе [Примеры](https://python-all.ru/3.10/library/importlib.html#importlib-examples) документации [`importlib`](https://python-all.ru/3.10/library/importlib.html#module-importlib).4647#### `imp.load_module(name, file, pathname, description)`4849Загружает модуль, который был ранее найден с помощью [`find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module) (или при другом поиске, давшем совместимые результаты). Эта функция делает больше, чем просто импорт модуля: если модуль уже был импортирован, она перезагружает его! Аргумент *name* указывает полное имя модуля (включая имя пакета, если это подмодуль пакета). Аргумент *file* – это открытый файл, а *pathname* – соответствующее имя файла; они могут быть `None` и `''`, соответственно, когда модуль является пакетом или не загружается из файла. Аргумент *description* – это кортеж, как возвращаемый [`get_suffixes()`](https://python-all.ru/3.10/library/imp.html#imp.get_suffixes), описывающий, какой тип модуля необходимо загрузить.5051Если загрузка успешна, возвращается объект модуля; в противном случае возбуждается исключение (обычно [`ImportError`](https://python-all.ru/3.10/library/exceptions.html#ImportError)).5253**Важно:** вызывающая сторона обязана закрыть аргумент *file*, если он не равен `None`, даже при возникновении исключения. Это лучше всего сделать с помощью оператора [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) … [`finally`](https://python-all.ru/3.10/reference/compound_stmts.html#finally).5455Устарело с версии 3.3: Если ранее использовался совместно с [`imp.find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module), рассмотрите возможность использования [`importlib.import_module()`](https://python-all.ru/3.10/library/importlib.html#importlib.import_module), в противном случае используйте загрузчик, возвращаемый заменой, выбранной для [`imp.find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module). Если вы вызывали [`imp.load_module()`](https://python-all.ru/3.10/library/imp.html#imp.load_module) и связанные функции напрямую с аргументами пути к файлу, используйте комбинацию [`importlib.util.spec_from_file_location()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.spec_from_file_location) и [`importlib.util.module_from_spec()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.module_from_spec). Подробности различных подходов см. в разделе [Примеры](https://python-all.ru/3.10/library/importlib.html#importlib-examples) документации [`importlib`](https://python-all.ru/3.10/library/importlib.html#module-importlib).5657#### `imp.new_module(name)`5859Возвращает новый пустой объект модуля с именем *name*. Этот объект *не* вставляется в `sys.modules`.6061Устарело с версии 3.4: Вместо этого используйте [`importlib.util.module_from_spec()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.module_from_spec).6263#### `imp.reload(module)`6465Перезагружает ранее импортированный модуль *module*. Аргумент должен быть объектом модуля, то есть он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля во внешнем редакторе и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение – объект модуля (тот же, что и аргумент *module*).6667Когда выполняется `reload(module)`:6869- Код модулей Python перекомпилируется, и код уровня модуля выполняется заново, определяя новый набор объектов, которые привязываются к именам в словаре модуля. Функция `init` модулей расширения не вызывается второй раз.70- Как и в случае со всеми другими объектами в Python, старые объекты освобождаются только после того, как их счётчики ссылок упадут до нуля.71- Имена в пространстве имён модуля обновляются, чтобы указывать на любые новые или изменённые объекты.72- Другие ссылки на старые объекты (например, имена вне модуля) не перепривязываются для указания на новые объекты и должны быть обновлены в каждом пространстве имён, где они встречаются, если это необходимо.7374Существует ряд других предостережений:7576При перезагрузке модуля его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имён заменяют старые определения, так что в целом это не проблема. Если новая версия модуля не определяет имя, которое было определено в старой версии, старое определение остаётся. Эта возможность может быть использована модулем с выгодой, если он поддерживает глобальную таблицу или кеш объектов – с помощью оператора [`try`](https://python-all.ru/3.10/reference/compound_stmts.html#try) он может проверить наличие таблицы и пропустить её инициализацию при необходимости:7778```python79try:80 cache81except NameError:82 cache = {}83```8485Перезагружать встроенные или динамически загружаемые модули допустимо, но обычно не очень полезно, за исключением [`sys`](https://python-all.ru/3.10/library/sys.html#module-sys), [`__main__`](https://python-all.ru/3.10/library/__main__.html#module-__main__) и [`builtins`](https://python-all.ru/3.10/library/builtins.html#module-builtins). Однако во многих случаях модули-расширения не рассчитаны на инициализацию более одного раза и могут отказывать в произвольных местах при перезагрузке.8687Если модуль импортирует объекты из другого модуля с помощью [`from`](https://python-all.ru/3.10/reference/simple_stmts.html#from) … [`import`](https://python-all.ru/3.10/reference/simple_stmts.html#import) …, вызов [`reload()`](https://python-all.ru/3.10/library/imp.html#imp.reload) для другого модуля не переопределяет импортированные из него объекты – один из способов обойти это – повторно выполнить оператор `from`, другой – использовать `import` и полные имена (*module*.\*name\*).8889Если модуль создаёт экземпляры класса, перезагрузка модуля, определяющего класс, не влияет на определения методов экземпляров – они продолжают использовать старое определение класса. То же самое верно для производных классов.9091Изменено в версии 3.3: Требуется, чтобы в перезагружаемом модуле были определены как `__name__`, так и `__loader__`, а не только `__name__`.9293Устарело с версии 3.4: Вместо этого используйте [`importlib.reload()`](https://python-all.ru/3.10/library/importlib.html#importlib.reload).9495Следующие функции предоставляют удобные средства для работы с путями к [**PEP 3147**](https://python-all.ru/3.10/library/imp.html) скомпилированным в байт-код файлам.9697Новое в версии 3.2.9899#### `imp.cache_from_source(path, debug_override=None)`100101Возвращает путь [**PEP 3147**](https://python-all.ru/3.10/library/imp.html) к файлу со скомпилированным байт-кодом, связанному с исходным *path*. Например, если *path* равен `/foo/bar/baz.py`, возвращаемое значение будет `/foo/bar/__pycache__/baz.cpython-32.pyc` для Python 3.2. Строка `cpython-32` берётся из текущего магического тега (см. [`get_tag()`](https://python-all.ru/3.10/library/imp.html#imp.get_tag); если `sys.implementation.cache_tag` не определён, будет возбуждено [`NotImplementedError`](https://python-all.ru/3.10/library/exceptions.html#NotImplementedError)). Передавая `True` или `False` для *debug\_override*, вы можете переопределить значение системы для `__debug__`, что приведёт к оптимизированному байт-коду.102103*path* не обязан существовать.104105Изменено в версии 3.3: Если `sys.implementation.cache_tag` равно `None`, то возбуждается [`NotImplementedError`](https://python-all.ru/3.10/library/exceptions.html#NotImplementedError).106107Устарело с версии 3.4: Вместо этого используйте [`importlib.util.cache_from_source()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.cache_from_source).108109Изменено в версии 3.5: Параметр *debug\_override* больше не создаёт файл `.pyo`.110111#### `imp.source_from_cache(path)`112113По *path* к имени файла [**PEP 3147**](https://python-all.ru/3.10/library/imp.html) возвращает путь к соответствующему файлу исходного кода. Например, если *path* равен `/foo/bar/__pycache__/baz.cpython-32.pyc`, возвращаемый путь будет `/foo/bar/baz.py`. *path* не обязан существовать, однако если он не соответствует формату [**PEP 3147**](https://python-all.ru/3.10/library/imp.html), возбуждается [`ValueError`](https://python-all.ru/3.10/library/exceptions.html#ValueError). Если `sys.implementation.cache_tag` не определён, возбуждается [`NotImplementedError`](https://python-all.ru/3.10/library/exceptions.html#NotImplementedError).114115Изменено в версии 3.3: Возбуждает [`NotImplementedError`](https://python-all.ru/3.10/library/exceptions.html#NotImplementedError), когда `sys.implementation.cache_tag` не определён.116117Устарело с версии 3.4: Вместо этого используйте [`importlib.util.source_from_cache()`](https://python-all.ru/3.10/library/importlib.html#importlib.util.source_from_cache).118119#### `imp.get_tag()`120121Возвращает строку магического тега [**PEP 3147**](https://python-all.ru/3.10/library/imp.html), соответствующую магическому числу этой версии Python, как возвращает [`get_magic()`](https://python-all.ru/3.10/library/imp.html#imp.get_magic).122123Устарело с версии 3.4: Используйте `sys.implementation.cache_tag` напрямую, начиная с Python 3.3.124125Следующие функции помогают взаимодействовать с внутренним механизмом блокировок системы импорта. Семантика блокировок импорта является деталью реализации, которая может меняться от версии к версии. Однако Python гарантирует, что циклические импорты работают без взаимных блокировок.126127#### `imp.lock_held()`128129Возвращает `True`, если глобальная блокировка импорта в данный момент удерживается, иначе `False`. На платформах без потоков всегда возвращает `False`.130131На платформах с потоками поток, выполняющий импорт, сначала удерживает глобальную блокировку импорта, затем устанавливает блокировку на каждый модуль для остальной части импорта. Это блокирует другие потоки от импорта того же модуля до завершения исходного импорта, предотвращая появление у других потоков неполных объектов модуля, созданных исходным потоком. Исключение делается для циклических импортов, которые по своей природе должны в какой-то момент предоставить неполный объект модуля.132133Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.134135Устарело с версии 3.4.136137#### `imp.acquire_lock()`138139Захватывает глобальную блокировку импорта интерпретатора для текущего потока. Эта блокировка должна использоваться хуками импорта для обеспечения потокобезопасности при импорте модулей.140141После того как поток захватил блокировку импорта, тот же поток может захватить её снова без блокировки; поток должен освобождать её один раз за каждый захват.142143На платформах без потоков эта функция ничего не делает.144145Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.146147Устарело с версии 3.4.148149#### `imp.release_lock()`150151Освобождает глобальную блокировку импорта интерпретатора. На платформах без поддержки потоков эта функция ничего не делает.152153Изменено в версии 3.3: Схема блокировки в основном изменилась на блокировки для каждого модуля. Глобальная блокировка импорта сохраняется для некоторых критических задач, таких как инициализация блокировок отдельных модулей.154155Устарело с версии 3.4.156157Следующие константы с целочисленными значениями, определённые в этом модуле, используются для указания результата поиска [`find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module).158159#### `imp.PY_SOURCE`160161Модуль найден как исходный файл.162163Устарело с версии 3.3.164165#### `imp.PY_COMPILED`166167Модуль найден как файл скомпилированного кода.168169Устарело с версии 3.3.170171#### `imp.C_EXTENSION`172173Модуль найден как динамически загружаемая общая библиотека.174175Устарело с версии 3.3.176177#### `imp.PKG_DIRECTORY`178179Модуль найден как каталог пакета.180181Устарело с версии 3.3.182183#### `imp.C_BUILTIN`184185Модуль найден как встроенный модуль.186187Устарело с версии 3.3.188189#### `imp.PY_FROZEN`190191Модуль найден как замороженный модуль.192193Устарело с версии 3.3.194195#### `class imp.NullImporter(path_string)`196197Тип [`NullImporter`](https://python-all.ru/3.10/library/imp.html#imp.NullImporter) – это хук импорта [**PEP 302**](https://python-all.ru/3.10/library/imp.html), который обрабатывает строки пути, не являющиеся каталогами, и не находит ни одного модуля. Вызов этого типа с существующим каталогом или пустой строкой вызывает [`ImportError`](https://python-all.ru/3.10/library/exceptions.html#ImportError). В противном случае возвращается экземпляр [`NullImporter`](https://python-all.ru/3.10/library/imp.html#imp.NullImporter).198199Экземпляры имеют только один метод:200201#### `find_module(fullname[, path])`202203Этот метод всегда возвращает `None`, указывая, что запрошенный модуль не найден.204205Изменено в версии 3.3: `None` вставляется в `sys.path_importer_cache` вместо экземпляра [`NullImporter`](https://python-all.ru/3.10/library/imp.html#imp.NullImporter).206207Устарело с версии 3.4: Вместо этого вставляйте `None` в `sys.path_importer_cache`.208209## Примеры210211Следующая функция эмулирует то, что было стандартным оператором импорта до Python 1.4 (без иерархических имён модулей). (Эта *реализация* не работала бы в той версии, так как [`find_module()`](https://python-all.ru/3.10/library/imp.html#imp.find_module) была расширена, а [`load_module()`](https://python-all.ru/3.10/library/imp.html#imp.load_module) был добавлен в 1.4.)212213```python214import imp215import sys216217def __import__(name, globals=None, locals=None, fromlist=None):218 # Быстрый путь: проверить, импортирован ли модуль ранее.219 try:220 return sys.modules[name]221 except KeyError:222 pass223224 # Если любой из следующих вызовов вызывает исключение,225 # возникает проблема, которую мы не можем обработать – пусть вызывающий код обработает её.226227 fp, pathname, description = imp.find_module(name)228229 try:230 return imp.load_module(name, fp, pathname, description)231 finally:232 # Так как возможен выход через исключение, необходимо явно закрыть fp.233 if fp:234 fp.close()235```236