Ленивый импорт из модуля (он же ленивая оценка переменной)Python

Программы на Python
Anonymous
Ленивый импорт из модуля (он же ленивая оценка переменной)

Сообщение Anonymous »


Отложенный импорт в Python уже давно обсуждается, и были сделаны некоторые предложения (например, PEP609 — Lazy Imports), чтобы сделать его встроенной (дополнительной) функцией в будущем.

Я разрабатываю пакет CLI, поэтому время запуска очень важно, и я хотел бы ускорить его за счет ленивой загрузки некоторых модулей, которые я использую.

Что у меня есть на данный момент
Изменив функцию для реализации отложенного импорта из документации Python importlib, я создал следующий класс LazyImport:

import importlib.util импортировать систему из типов импортировать ModuleType класс LazyImport: защита __init__(сам): проходить защита __new__( кл, название: ул., ) -> тип(ТипМодуля): пытаться: вернуть sys.modules[имя] кроме KeyError: спецификация = importlib.util.find_spec(имя) если спецификация: загрузчик = importlib.util.LazyLoader(spec.loader) spec.loader = загрузчик модуль = importlib.util.module_from_spec(spec) sys.modules[имя] = модуль loader.exec_module(модуль) возвратный модуль еще: поднять ModuleNotFoundError(f"Нет модуля с именем '{name}'") из None Примечание. Это лучший способ превратить функцию в класс, который я мог придумать, но я также буду рад отзывам по этому поводу, если у вас есть лучший способ.

Это отлично работает для импорта модулей верхнего уровня:

Вместо импорта (например) xarray как

импортировать xarray как xr Я бы побежал

xr = LazyImport('xarray') и все работает как положено, с той разницей, что модуль xarray добавляется в sys.modules, но он еще не загружен в память (скрипты модуля не беги еще).
Модуль загружается в память (поэтому сценарии модуля выполняются) только при первом обращении к переменной xr (например, путем вызова метода/подмодуля или просто путем ссылки на нее как есть). Итак, в приведенном выше примере любой из этих операторов загрузит модуль xarray в память:
[*]xr.DataArray([1,2,3]) [*]print(xr) [*]xr
Чего я хочу
Теперь я хотел бы иметь возможность добиться того же результата, но когда я загружаю класс, функцию или переменную из модуля.
Итак (например) вместо импорта класса xarray.DataArray через:

из xarray импортировать DataArray как Da Я хочу что-то вроде:

Da = LazyImport('DataArray', _from='xarray') так что модуль xarray добавляется в sys.modules, но еще не загружается в память и загружается только тогда, когда я впервые ссылаюсь на Da< /код> переменная. Переменная Da будет ссылаться на класс DataArray модуля xarray.

Что я пробовал
Я попробовал несколько вариантов, например

xr = LazyImport('xarray') Da = getattr(xr, 'DataArray') или изменив класс LazyImport, но каждый раз, когда я ссылаюсь на xr, модуль xarray загружается в память. Мне не удалось создать переменную Da без загрузки xarray в память.

Что касается примера, мне нужна, по сути, ленивая оценка переменной Da, которая оценивает (класс DataArray класса xarray модуль) только тогда, когда я впервые ссылаюсь на Da (и, следовательно, запускаю сценарии модуля только в этот момент).
Кроме того, я не хочу, чтобы для оцениваемой переменной Da вызывался какой-либо метод (например, Da.load()), но я хотите, чтобы переменная вычислялась напрямую при первом обращении к ней.

Я просмотрел некоторые внешние библиотеки (например, lazy_loader), но не нашел ни одной, которая позволяла бы отложенный импорт классов и переменных из внешних модулей (модулей, отличных от того, который вы разрабатываете).

Кто-нибудь знает решение для реализации отложенного импорта из модуля?

Вернуться в «Python»