Поскольку Google Translate API закрывается как бесплатный сервис, вы можете попробовать эту бесплатную альтернативу, заменяющую Google Translate API:
Мой, по сути, каталог с названием «плагины», который основное приложение может опрашивать, а затем использовать imp.load_module для получения файлов, ищите хорошо известный точка входа, возможно, с параметрами конфигурации на уровне модуля, и перейти оттуда. Я использую средства мониторинга файлов для определенной степени динамизма, при котором плагины активны, но это полезно иметь.
Конечно, любое возникающее требование говорит: «Мне не нужна [большая, сложная вещь ] X; Я просто хочу что-то легкое "рискует повторно реализовать X одно обнаруженное требование за раз. Но это не значит, что вы все равно не можете повеселиться :)
Мне понравилось обсуждение различных архитектур плагинов, проведенное доктором Андре Робержем на Pycon 2009. Он дает хороший обзор различных способов реализации плагинов, начиная с чего-то действительно простого.
Его доступен в виде подкаста (вторая часть после объяснения обезьяньего исправления), сопровождаемого серией из шести записей в блоге .
Я рекомендую быстро прослушать его, прежде чем делать решение.
Я биолог на пенсии, который занимался цифровыми микрографами и обнаружил, что ему нужно написать пакет обработки и анализа изображений (технически не библиотеку) для работы на машине SGi. Я написал код на C и использовал Tcl в качестве языка сценариев. Графический интерфейс в том виде, в каком он был, был выполнен с использованием Tk. Команды, появившиеся в Tcl, имели форму «extensionName commandName arg0 arg1 ... param0 param1 ...», то есть простые слова и числа, разделенные пробелами. Когда Tcl увидел подстроку extensionName, управление было передано пакету C. Это, в свою очередь, запустило команду через лексический анализатор / анализатор (выполненное в lex / yacc), а затем при необходимости вызвало подпрограммы C.
Команды для работы с пакетом могут запускаться одну за другой через окно в графическом интерфейсе пользователя, но пакетные задания выполнялись путем редактирования текстовых файлов, которые были действительными сценариями Tcl; вы должны выбрать шаблон, который выполняет нужную вам операцию на уровне файла, а затем отредактировать копию, чтобы она содержала фактические имена каталогов и файлов, а также команды пакета. Оно работало завораживающе. Пока ...
1) Мир превратился в ПК и 2) сценарии стали длиннее примерно 500 строк, когда сомнительные организационные возможности Tcl начали превращаться в настоящее неудобство. Прошло время ...
Я ушел на пенсию, был изобретен Python, и он выглядел как идеальный преемник Tcl. Я никогда не делал перенос, потому что я никогда не сталкивался с проблемами компиляции (довольно больших) программ C на ПК, расширения Python с помощью пакета C и создания графического интерфейса пользователя в Python / Gt? / Tk? /? ? Однако старая идея редактируемых шаблонных скриптов все еще работает. Также, ввод команд пакета в нативной форме Python не должен быть слишком большой проблемой, например:
packageName.command (arg0, arg1, ..., param0, param1, ...)
Несколько дополнительных точек , скобки и запятые, но это не остановка.
Я помню, как видел, что кто-то сделал версии lex и yacc на Python (попробуйте: http://www.dabeaz.com/ply/ ]), так что, если они все еще нужны, они есть.
Суть этой бессвязной беседы в том, что мне показалось, что сам Python ЯВЛЯЕТСЯ желаемым «легким» интерфейсом, который могут использовать ученые. Мне любопытно узнать, почему вы думаете, что это не так, и я серьезно об этом говорю.
добавлено позже: приложение gedit ожидает добавления плагинов, и на их сайте есть наиболее четкое объяснение простого плагин процедура I ' Я нашел за несколько минут, осмотревшись. Попробуйте:
https://wiki.gnome.org/Apps/Gedit/PythonPluginHowToOld
Я все же хотел бы лучше понять ваш вопрос. Мне неясно, 1) хотите ли вы, чтобы ученые могли довольно просто использовать ваше (Python) приложение различными способами, или 2) хотите, чтобы ученые могли добавлять новые возможности в ваше приложение. Выбор №1 - это ситуация, с которой мы столкнулись с изображениями, и которая заставила нас использовать общие сценарии, которые мы изменили в соответствии с потребностями момента. Является ли выбор №2, который приводит вас к идее плагинов, или это какой-то аспект вашего приложения, который делает невозможным выполнение команд для него?
Мне неясно, 1) хотите ли вы, чтобы ученые могли довольно просто использовать ваше (Python) приложение различными способами, или 2) хотите, чтобы ученые могли добавлять новые возможности в ваше приложение. Выбор №1 - это ситуация, с которой мы столкнулись с изображениями, и которая заставила нас использовать общие сценарии, которые мы изменили в соответствии с потребностями момента. Является ли выбор №2, который приводит вас к идее плагинов, или это какой-то аспект вашего приложения, который делает невозможным выполнение команд для него? Мне неясно, 1) хотите ли вы, чтобы ученые могли довольно просто использовать ваше (Python) приложение различными способами, или 2) хотите, чтобы ученые могли добавлять новые возможности в ваше приложение. Выбор №1 - это ситуация, с которой мы столкнулись с изображениями, и которая заставила нас использовать общие сценарии, которые мы изменили в соответствии с потребностями момента. Является ли выбор №2, который приводит вас к идее плагинов, или это какой-то аспект вашего приложения, который делает невозможным выполнение команд для него?Взгляните на в этом обзоре существующих фреймворков / библиотек плагинов , это хорошая отправная точка. Мне очень нравится yapsy , но это зависит от вашего варианта использования.
Хотя этот вопрос действительно интересен, я думаю, что на него довольно сложно ответить без дополнительных подробностей. Что это за приложение? У него есть графический интерфейс? Это инструмент командной строки? Набор скриптов? Программа с уникальной точкой входа и т. Д.
Учитывая небольшой объем информации, который у меня есть, я отвечу в очень общей форме.
Какие средства вы должны добавлять плагины?
На чистом уровне кода / дизайна вам нужно будет четко определить, какое поведение / конкретные действия вы хотите, чтобы ваши пользователи расширили. Определите общую точку входа / набор функций, которые всегда будут игнорироваться, и определите группы в рамках этих действий. Как только это будет сделано, вы сможете легко расширить ваше приложение,
Пример с использованием хуков , вдохновленный MediaWiki (PHP, но действительно ли язык имеет значение?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Другой пример, вдохновленный Mercurial . Здесь расширения только добавляют команды к исполняемому файлу командной строки hg , расширяя поведение.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Для обоих подходов вам могут потребоваться общие initialize и finalize для вашего расширение. Определите общую точку входа / набор функций, которые всегда будут игнорироваться, и определите группы в рамках этих действий. Как только это будет сделано, вы сможете легко расширить ваше приложение,
Пример с использованием хуков , вдохновленный MediaWiki (PHP, но действительно ли язык имеет значение?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Другой пример, вдохновленный Mercurial . Здесь расширения только добавляют команды к исполняемому файлу командной строки hg , расширяя поведение.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Для обоих подходов вам могут потребоваться общие initialize и finalize для вашего расширение. Определите общую точку входа / набор функций, которые всегда будут игнорироваться, и определите группы в рамках этих действий. Как только это будет сделано, вы сможете легко расширить ваше приложение,
Пример с использованием хуков , вдохновленный MediaWiki (PHP, но действительно ли язык имеет значение?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Другой пример, вдохновленный Mercurial . Здесь расширения только добавляют команды к исполняемому файлу командной строки hg , расширяя поведение.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Для обоих подходов вам могут потребоваться общие initialize и finalize для вашего расширение. но действительно ли язык имеет значение?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Другой пример, вдохновленный Mercurial. Здесь расширения только добавляют команды к исполняемому файлу командной строки hg , расширяя поведение.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Для обоих подходов вам могут потребоваться общие initialize и finalize для вашего расширение. но действительно ли язык имеет значение?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Другой пример, вдохновленный Mercurial. Здесь расширения только добавляют команды к исполняемому файлу командной строки hg , расширяя поведение.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Для обоих подходов вам могут потребоваться общие initialize и finalize для вашего расширение. You can either use a common interface that all your extension will have to implement (fits better with second approach; mercurial uses a reposetup(ui, repo) that is called for all extension), or use a hook-kind of approach, with a hooks.setup hook.
But again, if you want more useful answers, you'll have to narrow down your question ;)
module_example.py
:
def plugin_main(*args, **kwargs):
print args, kwargs
loader.py
:
def load_plugin(name):
mod = __import__("module_%s" % name)
return mod
def call_plugin(name, *args, **kwargs):
plugin = load_plugin(name)
plugin.plugin_main(*args, **kwargs)
call_plugin("example", 1234)
Это определенно «минимально», в нем нет абсолютно никакой проверки ошибок, возможно, бесчисленные проблемы с безопасностью, это не так. очень гибкий - но он должен показать вам, насколько простой может быть система плагинов в Python.
Возможно, вы захотите также изучить модуль imp , хотя вы можете многое сделать с помощью всего лишь __import __
, os.listdir
и некоторые манипуляции со строками.
Простая структура плагинов Марти Алчина - это база, которую я использую для своих нужд. Я действительно рекомендую взглянуть на него, я думаю, что это действительно хорошее начало, если вы хотите что-то простое и легко взломанное. Вы также можете найти его как фрагменты кода Django .