Я хотел бы включить Скрипты Python в одно из моих приложений, написанных на самом Python.
Мое приложение должно иметь возможность вызывать внешние функции Python (написанные пользователем) как обратные вызовы. Должен быть некоторый контроль над выполнением кода; например, если пользователь предоставил код с синтаксическими ошибками, приложение должно сообщить об этом.
Как лучше всего это сделать?
Спасибо.
редактировать: вопрос был непонятным. Мне нужен механизм, аналогичный событиям VBA, где есть раздел «объявлений» (где вы определяете глобальные переменные) и события со сценарием кода, которые запускаются в определенных точках.
Я разрабатываю инструмент анализа журналов, который можно было бы расширять / скриптовать (действия выполняются по мере чтения файлов журналов). Принцип таков: «каждое приложение на предприятии имеет свой собственный формат файла журнала, поэтому дайте пользователю возможность определять свои собственные правила мониторинга».






RestrictedPython предоставляет ограниченную среду выполнения для Python, например для запуска ненадежного кода.
Используйте __import__ для импорта файлов, предоставленных пользователем. Эта функция вернет модуль. Используйте это для вызова функций из импортированного файла.
Используйте try..except как на __import__, так и на самом вызове, чтобы отловить ошибки.
Пример:
m = None
try:
m = __import__("external_module")
except:
# invalid module - show error
if m:
try:
m.user_defined_func()
except:
# some error - display it
Если вы хотите, чтобы пользователь вводил команды в интерактивном режиме, я настоятельно рекомендую модуль код, часть стандартной библиотеки. Объекты InteractiveConsole и InteractiveInterpreter позволяют легко вводить и оценивать вводимые пользователем данные, а ошибки обрабатываются очень хорошо, а трассировки доступны, чтобы помочь пользователю сделать все правильно.
Только не забудьте поймать SystemExit!
$ python
Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> shared_var = "Set in main console"
>>> import code
>>> ic = code.InteractiveConsole({ 'shared_var': shared_var })
>>> try:
... ic.interact("My custom console banner!")
... except SystemExit, e:
... print "Got SystemExit!"
...
My custom console banner!
>>> shared_var
'Set in main console'
>>> shared_var = "Set in sub-console"
>>> sys.exit()
Got SystemExit!
>>> shared_var
'Set in main console'
«Мое приложение должно иметь возможность вызывать внешние функции Python (написанные пользователем) в качестве обратных вызовов».
Есть альтернатива, которая зачастую проще.
Определите классы, которые вызывают функции методов в определенных точках. Вы предоставляете реализацию по умолчанию.
Затем ваш пользователь может расширить классы и предоставить соответствующие функции методов вместо обратных вызовов.
Это редко требует глобальных переменных. Это также проще реализовать, потому что ваш пользователь делает что-то вроде следующего
import core_classes
class MyExtension( core_classes.SomeClass ):
def event_1( self, args ):
# override the default behavior for event_1.
core_classes.main( MyExtension )
Это работает очень плавно и обеспечивает максимальную гибкость. Ошибки всегда будут в их коде, так как их код является «основным» модулем.
Интересно, что это за приложение?