我正在开发一种用于对用户定义函数进行数值分析的工具。 我们的想法是在Python中创建一个方便的UI,用户可以在其中输入C函数,然后按下按钮 - 并接收一些输出数据。 计算可能需要几分钟或几小时,因此不能接受仅限Numpy的性能。
我尝试了以下方法:基于Python的UI调用gcc,从用户函数编译dll,这是我在Cython包装中使用的基于C的核心算法所使用的。它工作正常,但由于无法完全卸载python模块,因此在整个UI程序关闭并重新运行之前,我无法重新编译用户定义的函数。
我现在看到的唯一方法是将计算核心和UI流程分开,然后通过共享内存/消息传递进行交互。当用户想要更新他的功能时,程序终止核心,重新编译DLL并再次启动核心。
在这种情况下,您能否建议任何常见做法?
谢谢!
答案 0 :(得分:4)
Python有非常好的multiprocessing支持(并且实际上并不是很好的线程支持),所以你可以为每个要评估的表达式生成一个新的python进程,在新进程中编译和加载dll,然后有它将结果传递回父进程。当生成的进程退出时,应该卸载所有内容。
答案 1 :(得分:2)
每次用户输入一个函数时,您都可以生成一个具有随机唯一名称的新模块(就像您对临时文件所做的那样)。然后编译该模块,加载它,并调用该函数。
随着时间的推移,这当然会导致许多模块被加载。如果用户在单个会话中没有运行太多功能,您可能会侥幸逃脱。或者,您可以在普通DLL而不是Python模块中编译该函数,并使用ctypes加载它。当你完成DLL之后,只需丢弃对它的任何引用 - 当ctypes句柄最终被gced时,它应该卸载DLL(参见 How can I unload a DLL using ctypes in Python?)。
您可能还想从磁盘中删除DLL。如果您正在使用Windows,那可能会很棘手,因为很难预测ctypes何时会将其卸载,而Windows将不允许您将其删除它将被使用。
答案 2 :(得分:1)
您是否考虑过Weave或Instant(less up-to-date)?我自己只使用了瞬间,但对于你所描述的内容,似乎要么完美。
他们可以在运行时从字符串自动编译和缓存c代码。我只使用了即时内联c,但我确信它或编织也可以用于编译用户输入。
以下是tutorial。
中如何使用编织的示例>>> a = 'string'
>>> def protected_printf(a):
... assert(type(a) == type(1))
... weave.inline(r'printf("%d\n",a);',['a'])
>>> protected_printf(1)
1
>>> protected_printf('string')
AssertError...