2016-06-02 6 views
3

Я делаю библиотеку Python со следующей структурой:импорта по требованию для огромного импорта в __all__

my_amazing_lib 
+--- __init__.py 
+--- _core.py 
+--- _gui.py 

В __init__.py я следующее:

from ._core import core_lib 
from ._gui import huge_lib_with_gui 

__all__ = ['core_lib', 'huge_lib_with_gui'] 

Цель состоит в том, чтобы обеспечить АНИ для пользователей, так что они могут использовать либо:

  1. from my_amazing_lib import core_lib
  2. или from my_amazing_lib import huge_lib_with_gui

в зависимости от их потребностей.

Проблема заключается в том, что Python автоматически импортирует huge_lib_with_gui, даже если пользователю нужно только core_lib, и это может вызвать различные проблемы: проблемы с зависимостями (GUI библиотеки для примера), замедление (например, huge_lib_with_gui нерестится несколько потоков и фоновых заданий, тогда как core_lib не нужно это делать) и т. д. Этот вопрос уже был described here (Ловушка № 2).

Есть ли способ объявить открытый API для модуля в Python но импорта только уместен субмодуль на потребности пользователей?

Решение должно работать как для Python 2.7.10, так и для Python> 3.3.

+0

Почему бы не просто «импортировать my_amazing_lib._core.core_lib'? –

+0

Я предполагаю, что вы имели в виду 'import my_amazing_lib._core.core_lib'. Это возможно, но не решает проблему: я должен удалить '' '__all__''', который служит дескриптором API. Либо я отбрасываю API, либо я принимаю, что все импорт выполнен, и проблемы, которые возникают. Я ищу альтернативу, которая могла бы согласовать оба (сохранить API, но не выполнять импорт, если это необходимо). – gaborous

+0

Зачем вам нужен дескриптор API? Я понимаю, что вы не хотите импортировать больше, чем необходимо (Trap n ° 2).Но почему '__all__'? Для чего его используют? –

ответ

0

Я предлагаю хранить дорогостоящие части библиотеки в отдельном подмодуле, а не включать его непосредственно в пространство имен пакетов верхнего уровня. Хотя вы можете использовать функции прокси, чтобы выставлять API дорогостоящих битов в пространстве имен верхнего уровня без предварительного импорта всего этого, это, вероятно, больше проблем, чем его ценность.

Например, в вашем примере макета упаковки:

my_amazing_lib 
+--- __init__.py 
+--- _core.py 
+--- _gui.py 

Вы можете добавить gui.py файл, который импортирует публичный API из _gui в чистое пространство имен.

The содержание gui.py будет:

from ._gui import huge_lib_with_a_gui 

__all__ = ["huge_lib_with_a_gui"] 

и __init__.py файл будет выглядеть следующим образом:

from ._core import core_lib 

__all__ = ["core_lib", "gui"] # don't import gui here, just name it as part of `__all__` 

пользователей, которые нуждаются только основные части вашей библиотеки могут сделать from my_amazing_lib import core_lib и пользователей, которые нуждаются в gui тоже может добавить from my_amazing_lib.gui import huge_lib_with_a_gui.

Смежные вопросы