Подтвердить что ты не робот

Какая хорошая практика Python для импорта и предоставления дополнительных функций?

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

---- IN LOADING FUNCTION ----
features = []

for path in sys.path:
       if os.path.exists(os.path.join(path, 'pynotify')):
              features.append('pynotify')
       if os.path.exists(os.path.join(path, 'gnomekeyring.so')):
              features.append('gnome-keyring')

#user dialog to ask for stuff
#notifications available, do you want them enabled?
dlg = ConfigDialog(features)

if not dlg.get_notifications():
    features.remove('pynotify')


service_start(features ...)

---- SOMEWHERE ELSE ------

def service_start(features, other_config):

        if 'pynotify' in features:
               import pynotify
               #use pynotify...

Однако есть некоторые проблемы. Если пользователь форматирует свой компьютер и устанавливает новейшую версию своей ОС и перераспределяет это приложение, функции внезапно исчезают без предупреждения. Решение должно представить это в окне конфигурации:

if 'pynotify' in features:
    #gtk checkbox
else:
    #gtk label reading "Get pynotify and enjoy notification pop ups!"

Но если это так, мак, откуда я знаю, что я не отправляю пользователя на дикую охоту за гусями, ища зависимость, которую они никогда не могут заполнить?

Вторая проблема:

if os.path.exists(os.path.join(path, 'gnomekeyring.so')):

вопрос. Могу ли я быть уверенным, что файл всегда называется gnomekeyring.so во всех дистрибутивах Linux?

Как другие люди проверяют эти функции? Проблема с базовым

try:
    import pynotify
except:
    pynotify = disabled

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

Так что думают люди, это лучший способ решить эту проблему?

4b9b3361

Ответ 1

Возможно, вам стоит взглянуть на модуль imp, который в основном делает то, что вы делаете вручную выше. Поэтому вы можете сначала найти модуль с find_module(), а затем загрузить его через load_module() или просто импортировать его (после проверки конфигурации).

И btw, если использовать за исключением: я всегда добавлял бы к нему конкретное исключение (здесь ImportError), чтобы случайно не поймать несвязанные ошибки.

Ответ 2

Метод try: не должен быть глобальным - его можно использовать в любой области, и поэтому модули могут быть "ленивыми" во время выполнения. Например:

def foo():
    try:
        import external_module
    except ImportError:
        pass

    if external_module:
        external_module.some_whizzy_feature()
    else:
        print "You could be using a whizzy feature right now, if you had external_module."

При запуске script не будет предпринята попытка загрузить external_module. В первый раз вызывается foo(), external_module (если доступно) загружается и вставляется в локальную область функции. Последующие вызовы foo() повторно вставляют external_module в свою область действия без необходимости перезагрузки модуля.

В общем, лучше всего позволить Python обрабатывать логику импорта - это делалось некоторое время.: -)

Ответ 3

Один из способов решения проблемы разных зависимостей для разных функций - реализовать дополнительные функции в виде плагинов. Таким образом, у пользователя есть контроль над тем, какие функции активированы в приложении, но не отвечает за отслеживание самих зависимостей. Затем эта задача обрабатывается во время каждой установки плагина.