Спасибо Андре за ответ - так просто!
Для тех из вас, кому это небезразлично, возможно, мне следовало бы включить весь контекст проблемы. Вот это все равно:
В моем приложении пользователи могут писать плагины на python. Они должны определять функцию с четко определенным списком параметров, но я не хотел навязывать им какие-либо соглашения об именах.
Итак, пока пользователи пишут функцию с правильным количеством параметров и типов, все, что им нужно сделать, это что-то вроде этого (помните, это код плагина):
# this is my custom code - all plugins are called with a modified sys.path, so this
# imports some magic python code that defines the functions used below.
from specialPluginHelperModule import *
# define the function that does all the work in this plugin:
def mySpecialFn(paramA, paramB, paramC):
# do some work here with the parameters above:
pass
# set the above function:
setPluginFunction(mySpecialFn)
Вызов setPluginFunction
берет объект функции и устанавливает его в скрытом объекте класса (наряду с другими вещами, относящимися к конфигурации плагинов, этот пример несколько упрощен). Когда основное приложение хочет запустить функцию, я использую модуль runpy
для запуска кода плагина, а затем извлекаю объект класса, упомянутый выше, - это дает мне данные конфигурации и функцию плагина, чтобы я мог запустить его без ошибок загрязняет мое пространство имен).
Весь этот процесс повторяется несколько раз для разных плагинов на одном и том же входе и, кажется, работает очень хорошо для меня.