> **Источник:** https://python-all.ru/3.0/library/imp.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# `imp` – доступ к внутренностям [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import)

Этот модуль предоставляет интерфейс к механизмам, используемым для реализации оператора [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import). Он определяет следующие константы и функции:

#### `[imp.get_magic]imp.get_magic()`

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

#### `[imp.get_suffixes]imp.get_suffixes()`

Возвращает список трёхэлементных кортежей, каждый из которых описывает конкретный тип модуля. Каждая тройка имеет вид

`(suffix, mode, type)`

, где

*suffix*

– строка, добавляемая к имени модуля для формирования имени файла для поиска,

*mode*

– строка режима, передаваемая встроенной функции

[`open()`](https://python-all.ru/3.0/library/functions.html#open)

для открытия файла (это может быть

`'r'`

для текстовых файлов или

`'rb'`

для двоичных файлов), а

*type*

– тип файла, который принимает одно из значений

[`PY_SOURCE`](https://python-all.ru/3.0/library/imp.html#imp.PY_SOURCE)

,

[`PY_COMPILED`](https://python-all.ru/3.0/library/imp.html#imp.PY_COMPILED)

или

[`C_EXTENSION`](https://python-all.ru/3.0/library/imp.html#imp.C_EXTENSION)

, описанных ниже.

#### `[imp.find_module]imp.find_module(name[, path])`

Пытается найти модуль *name* на пути поиска *path*. Если *path* – список имён каталогов, каждый каталог проверяется на наличие файлов с любым из суффиксов, возвращаемых [`get_suffixes()`](https://python-all.ru/3.0/library/imp.html#imp.get_suffixes) выше. Некорректные имена в списке игнорируются без сообщений (но все элементы списка должны быть строками). Если *path* опущен или равен `None`, выполняется поиск по списку имён каталогов, заданному `sys.path`, но сначала проверяются несколько особых мест: предпринимается попытка найти встроенный модуль с указанным именем ([`C_BUILTIN`](https://python-all.ru/3.0/library/imp.html#imp.C_BUILTIN)), затем замороженный модуль ([`PY_FROZEN`](https://python-all.ru/3.0/library/imp.html#imp.PY_FROZEN)), а на некоторых системах также проверяются и другие места (в Windows – реестр, который может указывать на конкретный файл).

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

*file* – это открытый файловый объект, установленный в начало, *pathname* – это имя пути найденного файла, а *description* – кортеж из 3 элементов, как содержащийся в списке, возвращаемом [`get_suffixes()`](https://python-all.ru/3.0/library/imp.html#imp.get_suffixes), описывающий тип найденного модуля.

Если модуль не находится в файле, возвращаемый *file* равен `None`, *pathname* – пустая строка, а кортеж *description* содержит пустые строки для суффикса и режима; тип модуля указывается, как показано выше в скобках. Если поиск неуспешен, возбуждается [`ImportError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.ImportError). Другие исключения указывают на проблемы с аргументами или окружением.

Если модуль является пакетом, *file* равен `None`, *pathname* – путь к пакету, а последним элементом кортежа *description* является [`PKG_DIRECTORY`](https://python-all.ru/3.0/library/imp.html#imp.PKG_DIRECTORY).

Эта функция не работает с иерархическими именами модулей (именами, содержащими точки). Чтобы найти *P*.\*M\*, то есть подмодуль *M* пакета *P*, используйте [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module) и [`load_module()`](https://python-all.ru/3.0/library/imp.html#imp.load_module) для поиска и загрузки пакета *P*, а затем вызовите [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module) с аргументом *path*, установленным в `P.__path__`. Если *P* сам содержит точку, применяйте этот рецепт рекурсивно.

#### `[imp.load_module]imp.load_module(name, file, pathname, description)`

Загружает модуль, который ранее был найден с помощью [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module) (или другого поиска, давшего совместимые результаты). Эта функция делает больше, чем просто импорт модуля: если модуль уже был импортирован, она перезагружает его! Аргумент *name* указывает полное имя модуля (включая имя пакета, если это подмодуль пакета). Аргумент *file* – это открытый файл, а *pathname* – соответствующее имя файла; они могут быть `None` и `''` соответственно, когда модуль является пакетом или не загружается из файла. Аргумент *description* – это кортеж, такой, какой вернула бы [`get_suffixes()`](https://python-all.ru/3.0/library/imp.html#imp.get_suffixes), описывающий, какой тип модуля должен быть загружен.

Если загрузка успешна, возвращается объект модуля; в противном случае возбуждается исключение (обычно [`ImportError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.ImportError)).

**Важно:** вызывающий код отвечает за закрытие аргумента *file*, если он не был `None`, даже при возбуждении исключения. Лучше всего это делать с помощью оператора [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) ... [`finally`](https://python-all.ru/3.0/reference/compound_stmts.html#finally).

#### `[imp.new_module]imp.new_module(name)`

Возвращает новый пустой объект модуля с именем

*name*

. Этот объект

*не*

вставляется в

`sys.modules`

.

#### `[imp.lock_held]imp.lock_held()`

Возвращает `True`, если блокировка импорта в данный момент удерживается, иначе `False`. На платформах без потоков всегда возвращает `False`.

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

#### `[imp.acquire_lock]imp.acquire_lock()`

Захватывает блокировку импорта интерпретатора для текущего потока. Эта блокировка должна использоваться хуками импорта для обеспечения потокобезопасности при импорте модулей. На платформах без поддержки потоков эта функция ничего не делает.

После того как поток захватил блокировку импорта, тот же поток может захватить её снова без блокировки; поток должен освобождать её один раз за каждый захват.

На платформах без потоков эта функция ничего не делает.

#### `[imp.release_lock]imp.release_lock()`

Освобождает блокировку импорта интерпретатора. На платформах без потоков эта функция ничего не делает.

#### `[imp.reload]imp.reload(module)`

Перезагружает ранее импортированный модуль *module*. Аргумент должен быть объектом модуля, то есть он должен быть успешно импортирован ранее. Это полезно, если вы отредактировали исходный файл модуля во внешнем редакторе и хотите опробовать новую версию, не выходя из интерпретатора Python. Возвращаемое значение – объект модуля (тот же, что и аргумент *module*).

При выполнении `reload(module)`:

- Код модулей Python перекомпилируется, и код уровня модуля выполняется заново, определяя новый набор объектов, которые привязываются к именам в словаре модуля. Функция `init` модулей расширения не вызывается второй раз.
- Как и в случае со всеми другими объектами в Python, старые объекты освобождаются только после того, как их счётчики ссылок упадут до нуля.
- Имена в пространстве имён модуля обновляются, чтобы указывать на любые новые или изменённые объекты.
- Другие ссылки на старые объекты (например, имена вне модуля) не перепривязываются для указания на новые объекты и должны быть обновлены в каждом пространстве имён, где они встречаются, если это необходимо.

Существует ряд других предостережений:

Если модуль синтаксически корректен, но его инициализация завершается ошибкой, первый оператор [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import) для него не связывает имя локально, но сохраняет (частично инициализированный) объект модуля в `sys.modules`. Чтобы перезагрузить модуль, сначала нужно снова выполнить [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import) (это свяжет имя с частично инициализированным объектом модуля), и только затем можно вызвать для него [`reload()`](https://python-all.ru/3.0/library/imp.html#imp.reload).

При перезагрузке модуля его словарь (содержащий глобальные переменные модуля) сохраняется. Переопределения имён заменяют старые определения, так что обычно это не проблема. Если новая версия модуля не определяет имя, которое было определено в старой версии, старое определение остаётся. Эту возможность можно использовать в пользу модуля, если он поддерживает глобальную таблицу или кеш объектов – с помощью оператора [`try`](https://python-all.ru/3.0/reference/compound_stmts.html#try) он может проверить наличие таблицы и, если нужно, пропустить её инициализацию:

```python
try:
    cache
except NameError:
    cache = {}
```

Перезагрузка встроенных или динамически загружаемых модулей допустима, но обычно не очень полезна, за исключением [`sys`](https://python-all.ru/3.0/library/sys.html#module-sys), [`__main__`](https://python-all.ru/3.0/library/__main__.html#module-__main__) и `__builtin__`. Однако во многих случаях модули расширения не рассчитаны на инициализацию более одного раза и могут произвольно завершаться ошибкой при перезагрузке.

Если модуль импортирует объекты из другого модуля с помощью [`from`](https://python-all.ru/3.0/reference/simple_stmts.html#from) ... [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import) ..., то вызов [`reload()`](https://python-all.ru/3.0/library/imp.html#imp.reload) для другого модуля не переопределяет импортированные из него объекты. Один из способов обойти это – повторно выполнить оператор [`from`](https://python-all.ru/3.0/reference/simple_stmts.html#from), другой – использовать [`import`](https://python-all.ru/3.0/reference/simple_stmts.html#import) и квалифицированные имена (*module*.\*name\*).

Если модуль создаёт экземпляры класса, перезагрузка модуля, определяющего класс, не влияет на определения методов экземпляров – они продолжают использовать старое определение класса. То же самое верно для производных классов.

#### `imp.acquire_lock()`

Захватывает блокировку импорта интерпретатора для текущего потока. Эта блокировка должна использоваться хуками импорта для обеспечения потокобезопасности при импорте модулей. На платформах без поддержки потоков эта функция ничего не делает.

#### `imp.release_lock()`

Освобождает блокировку импорта интерпретатора. На платформах без потоков эта функция ничего не делает.

Следующие константы с целочисленными значениями, определённые в этом модуле, используются для указания результата поиска [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module).

#### `[imp.PY_SOURCE]imp.PY_SOURCE`

Модуль найден как исходный файл.

#### `[imp.PY_COMPILED]imp.PY_COMPILED`

Модуль найден как файл скомпилированного кода.

#### `[imp.C_EXTENSION]imp.C_EXTENSION`

Модуль найден как динамически загружаемая общая библиотека.

#### `[imp.PKG_DIRECTORY]imp.PKG_DIRECTORY`

Модуль найден как каталог пакета.

#### `[imp.C_BUILTIN]imp.C_BUILTIN`

Модуль найден как встроенный модуль.

#### `[imp.PY_FROZEN]imp.PY_FROZEN`

Модуль был найден как замороженный модуль (см.

[`init_frozen()`](https://python-all.ru/3.0/library/imp.html#imp.init_frozen)

).

Следующая константа и функции устарели; их функциональность доступна через [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module) или [`load_module()`](https://python-all.ru/3.0/library/imp.html#imp.load_module). Они сохранены для обратной совместимости:

#### `[imp.SEARCH_ERROR]imp.SEARCH_ERROR`

Не используется.

#### `[imp.init_builtin]imp.init_builtin(name)`

Инициализирует встроенный модуль с именем

*name*

и возвращает его объект модуля, а также сохраняет его в

`sys.modules`

. Если модуль уже был инициализирован, он будет инициализирован

*заново*

. Повторная инициализация включает копирование

`__dict__`

встроенного модуля из кешированного модуля в запись модуля в

`sys.modules`

. Если встроенный модуль с именем

*name*

отсутствует, возвращается

`None`

.

#### `[imp.init_frozen]imp.init_frozen(name)`

Инициализирует замороженный модуль с именем

*name*

и возвращает его объект модуля. Если модуль уже был инициализирован, он будет инициализирован

*снова*

. Если замороженный модуль с именем

*name*

отсутствует, возвращается

`None`

. (Замороженные модули – это модули, написанные на Python, чей скомпилированный байт-код включён в специально собранный интерпретатор Python с помощью утилиты

**freeze**

комплекта Python. См.

`Tools/freeze/`

пока.)

#### `[imp.is_builtin]imp.is_builtin(name)`

Возвращает

`1`

, если существует встроенный модуль с именем

*name*

, который можно инициализировать заново. Возвращает

`-1`

, если существует встроенный модуль с именем

*name*

, который нельзя инициализировать заново (см.

[`init_builtin()`](https://python-all.ru/3.0/library/imp.html#imp.init_builtin)

). Возвращает

`0`

, если нет встроенного модуля с именем

*name*

.

#### `[imp.is_frozen]imp.is_frozen(name)`

Возвращает

`True`

, если существует замороженный модуль (см.

[`init_frozen()`](https://python-all.ru/3.0/library/imp.html#imp.init_frozen)

) с именем

*name*

, или

`False`

, если такого модуля нет.

#### `[imp.load_compiled]imp.load_compiled(name, pathname[, file])`

Загружает и инициализирует модуль, реализованный как файл с байт-кодом, и возвращает его объект модуля. Если модуль уже был инициализирован, он будет инициализирован *заново*. Аргумент *name* используется для создания или доступа к объекту модуля. Аргумент *pathname* указывает на файл с байт-кодом. Аргумент *file* – это файл с байт-кодом, открытый для чтения в двоичном режиме с начала. В настоящее время это должен быть реальный файловый объект, а не пользовательский класс, эмулирующий файл.

#### `[imp.load_dynamic]imp.load_dynamic(name, pathname[, file])`

Загружает и инициализирует модуль, реализованный как динамически загружаемая разделяемая библиотека, и возвращает его объект модуля. Если модуль уже был инициализирован, он будет инициализирован

*заново*

. Повторная инициализация включает копирование атрибута

`__dict__`

кэшированного экземпляра модуля в значение, используемое в модуле, кэшированном в

`sys.modules`

. Аргумент

*pathname*

должен указывать на разделяемую библиотеку. Аргумент

*name*

используется для построения имени функции инициализации: вызывается внешняя C-функция с именем

`initname()`

в разделяемой библиотеке. Необязательный аргумент

*file*

игнорируется. (Примечание: использование разделяемых библиотек сильно зависит от системы, и не все системы их поддерживают.)

#### `[imp.load_source]imp.load_source(name, pathname[, file])`

Загружает и инициализирует модуль, реализованный как исходный файл Python, и возвращает его объект модуля. Если модуль уже был инициализирован, он будет инициализирован

*заново*

. Аргумент

*name*

используется для создания или доступа к объекту модуля. Аргумент

*pathname*

указывает на исходный файл. Аргумент

*file*

– это исходный файл, открытый для чтения как текст с начала. В настоящее время это должен быть реальный файловый объект, а не пользовательский класс, эмулирующий файл. Обратите внимание, что если существует соответствующий файл с байт-кодом (с суффиксом

`.pyc`

или

`.pyo`

), он будет использован вместо разбора данного исходного файла.

#### `[imp.NullImporter]class imp.NullImporter(path_string)`

Тип [`NullImporter`](https://python-all.ru/3.0/library/imp.html#imp.NullImporter) – это хук импорта по [**PEP 302**](https://python-all.ru/3.0/library/imp.html), который обрабатывает строки пути, не являющиеся каталогами, возвращая отказ в поиске любых модулей. Вызов этого типа с существующим каталогом или пустой строкой возбуждает [`ImportError`](https://python-all.ru/3.0/library/exceptions.html#exceptions.ImportError). В противном случае возвращается экземпляр [`NullImporter`](https://python-all.ru/3.0/library/imp.html#imp.NullImporter).

Python добавляет экземпляры этого типа в `sys.path_importer_cache` для любых записей пути, которые не являются каталогами и не обрабатываются никакими другими хуками пути из `sys.path_hooks`. Экземпляры имеют только один метод:

#### `[imp.NullImporter.find_module]find_module(fullname[, path])`

Этот метод всегда возвращает

`None`

, указывая, что запрошенный модуль не найден.

## Примеры

Следующая функция эмулирует то, что было стандартным оператором импорта до Python 1.4 (без иерархических имён модулей). (Эта *реализация* не работала бы в той версии, поскольку [`find_module()`](https://python-all.ru/3.0/library/imp.html#imp.find_module) была расширена, а [`load_module()`](https://python-all.ru/3.0/library/imp.html#imp.load_module) добавлена в версии 1.4.)

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

Более полный пример, который реализует иерархические имена модулей и содержит функцию [`reload()`](https://python-all.ru/3.0/library/imp.html#imp.reload), можно найти в модуле `knee`. Модуль `knee` находится в каталоге `Demo/imputil/` дистрибутива исходного кода Python.
