Стоп мышления с точки зрения имен путей и начать думать в терминах пакетов. Прочтите Packages в учебнике, и если вы хотите более подробно, см. The import system.
Но основная идея заключается в следующем:
Создать имя файла plugins/__init__.py
. Он может быть пустым; этого достаточно, чтобы включить plugins
в пакет . Это означает, что вы можете импортировать модули из этого пакета с помощью:
import plugins.plugin
Итак, как вы это делаете динамически? Вот для чего importlib
. (Вы также можете использовать __import__
здесь, но это менее гибкий и менее читаемым в нетривиальных случаях, поэтому если вам не нужно предварительно 3.3 совместимости, нет.)
plugin = importlib.import_module('plugins.{name}'.format(name=pluginname))
Это, вероятно, будет чище для import plugins
для получения пакета, а затем использовать относительный импорт из этого пакета, как показано в примерах в документах import_module
.
Это также означает, что Python заботится о .pyc создания и кэширования и т.д.
А это значит, что вы можете позже расширить plugins
быть «пространство имен пакета», который может быть разделен на несколько каталогов, как /usr/share/myapp/plugins
для платных плагинов, /etc/myapp/plugins
для плагинов сайта и ~/myapp/plugins
для пользовательских плагинов.
Если вы действительно, действительно хотите импортировать из каталога, который не является пакет, вы можете создать модуль загрузчика и использовать его, но это в целом много работы не реальной пользы. (На самом деле это не так сложно в 3.3 (SourceLoader
, и друзья будут делать большую часть работы за вас), но вы не найдете практически никаких примеров для руководства, вместо этого вы найдете примеры пути 2.6-3.2 или 2.0-2.5, оба из которых - это.) Кроме того, это означает, что если кто-то создает плагин с именем, скажем, gzip
, вы можете в конечном итоге заблокировать модуль stdlib gzip
с помощью плагина. (Это особенно забавно, если плагин gzip
пытается использовать модуль stdlib , так как он, вероятно, будет ...) Если плагин заканчивается именем plugins.gzip
, проблем нет.
Кроме того, в качестве побочного вопроса, то, как я пытаюсь достичь расширяемости это хороший способ?
Пока вы только хотите поддержать 3.3+, да, я думаю, что это отличное решение.
До 3.3 использование пакета для плагинов было намного более проблематичным. Люди придумали множество различных систем плагинов - в одном случае, вплоть до динамического создания объектов модуля и execfile
. Если вам нужно это решить, я бы предложил посмотреть существующие приложения Python с плагинами (например, MusicBrainz Picard), чтобы получить разные идеи.
Спасибо за пример! Я действительно не мог понять, как работал importlib. – gcq