Python运行时:重新编译和重用C库

我正在开发一种用于对用户定义函数进行数值分析的工具。 我们的想法是在Python中创建一个方便的UI,用户可以在其中输入C函数,然后按下按钮 – 并接收一些输出数据。 计算可能需要几分钟或几小时,因此不能接受仅限Numpy的性能。

我尝试了以下方法:基于Python的UI调用gcc,从用户函数编译dll,这是我在Cython包装中使用的基于C的核心算法所使用的。 它工作,但由于没有办法完全卸载python模块,我不能重新编译用户定义的函数,直到整个UI程序关闭并再次运行。

我现在看到的唯一方法是分离计算核心和UI进程,然后通过共享内存/消息传递使它们进行交互。 当用户想要更新他的function时,程序终止核心,重新编译DLL并再次启动核心。

在这种情况下你能建议任何常见做法吗?

谢谢!

Python具有非常好的多处理支持(并且实际上不是很好的线程支持),所以你可以为每个要评估的表达式生成一个新的python进程,在新进程中编译和加载dll,然后让它将结果传回给父进程。 当生成的进程退出时,应该卸载所有内容。

每次用户输入函数时,您都可以生成一个具有随机唯一名称的新模块(就像您对临时文件所做的那样)。 然后编译该模块,加载它并调用该函数。

随着时间的推移,这当然会导致许多模块被加载。 如果用户在单个会话中没有运行太多function,您可能会侥幸逃脱。 或者,您可以在普通DLL而不是Python模块中编译该函数,并使用ctypes加载它。 当你完成DLL之后,只需丢弃对它的任何引用 – 当ctypes句柄最终被gced时,它应该卸载DLL(请参阅如何在Python中使用ctypes卸载DLL? )。

您可能还想从磁盘中删除DLL。 如果您正在使用Windows,那可能会很棘手,因为很难预测ctypes何时会将其卸载,并且Windows将不允许您删除它,它将被使用。

您是否考虑过Weave或Instant ( 不太新 )? 我自己只使用了瞬间,但它似乎对你所描述的内容都是完美的。

它们可以在运行时从字符串自动编译和缓存c代码。 我只使用了即时内联c,但我确信它或编织也可以用于编译用户输入。

以下是教程中如何使用weave的示例 。

>>> 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...