Резюме
Я работаю над серией дополнений для Anki, программы с открытым исходным кодом. Дополнения Anki поставляются в виде пакетов Python, а основная структура папок выглядит следующим образом:
anki_addons/
addon_name_1/
__init__.py
addon_name_2/
__init__.py
anki_addons
добавляется к sys.path
базовым приложением, которое затем импортирует каждый add_on с import <addon_name>
.
Проблема, которую я пытаюсь решить, заключается в том, чтобы найти надежный способ отправки пакетов и их зависимостей с моими дополнениями, не загрязняя глобальное состояние или не возвращаясь к ручным изменениям пакетов поставщиков.
конкретика
В частности, учитывая такую дополнительную структуру...
addon_name_1/
__init__.py
_vendor/
__init__.py
library1
library2
dependency_of_library2
...
... Я хотел бы иметь возможность импортировать любой произвольный пакет, который включен в каталог _vendor
, например:
from ._vendor import library1
Основная проблема с относительным импортом, как это, заключается в том, что они не работают для пакетов, которые также зависят от других пакетов, импортированных через абсолютные ссылки (например, import dependency_of_library2
в исходный код library2
)
Решение
До сих пор я изучил следующие варианты:
- Ручное обновление сторонних пакетов, чтобы их операторы импорта указывали на полный путь к модулю в моем пакете python (например,
import addon_name_1._vendor.dependency_of_library2
). Но это утомительная работа, которая не масштабируется для больших деревьев зависимостей, а не переносима в другие пакеты. - Добавление
_vendor
вsys.path
черезsys.path.insert(1, <path_to_vendor_dir>)
в файле инициализации пакета. Это работает, но оно вводит глобальное изменение в путь поиска модуля, который будет влиять на другие надстройки и даже на базовое приложение. Это похоже на хак, который может привести к появлению проблемы с пандорой позже (например, конфликты между различными версиями одного и того же пакета и т.д.). - Временное изменение sys.path для моего импорта; но это не работает для сторонних модулей с импортом уровня метода.
- Написание пользовательского импортера PEP302 -style основано на примере, который я нашел в setuptools, но я просто не мог сделать этого или нет.
Я застрял на этом в течение нескольких часов, и я начинаю думать, что я либо полностью пропустил простой способ сделать это, либо что есть что-то принципиально неправильное для всего моего подхода.
Разве я не могу отправить дерево зависимостей сторонних пакетов с моим кодом, не прибегая к sys.path
или изменяя пакеты, о которых идет речь?
Редактировать:
Просто уточнить: у меня нет никакого контроля над тем, как надстройки импортируются из папки anki_addons. anki_addons - это только каталог, предоставляемый базовым приложением, в котором установлены все надстройки. Он добавляется к пути sys, поэтому надменные пакеты в нем в значительной степени просто ведут себя как любой другой пакет python, расположенный в путях поиска Python.