如何使用pyximport交互式地重新加载Cython模块

24

写Python代码时,我的典型工作流程是使用交互式提示符并执行类似以下的操作:

write function
repeat until working:
  test function
  edit function

一旦我确认一切正常,我将以非交互模式运行代码并收集结果。

有时函数运行速度有点慢,必须进行优化。

我有兴趣使用Cython优化这些缓慢的函数,但是我想保持我的交互式工作流程,即运行函数,进行更改,再次运行。

有没有简单的方法可以做到这一点?

到目前为止,我已经尝试将我的Cython函数放入一个单独的模块 "my_functions.pyx":

def fun1(int x):
    return x + 130

def fun2(int x):
    return x / 30

然后在交互式提示符下运行:

import pyximport; pyximport.install()
import my_functions as mf
mf.fun1(25)

这可以在第一次运行时工作,但我想对我的Cython函数进行更改并在同一个交互会话中重新加载它们。

运行中

import my_functions as mf

完全不更新这些函数。 而且运行

reload(mf)

出现错误: No module named my_functions

唯一有效的方法是退出当前会话,重新启动ipython,然后再次导入模块。但这样做基本上破坏了交互式运行的好处。

有更好的方法在Cython中进行交互式函数优化吗?

如果没有,您能描述一些其他使用Cython优化代码的方法吗?

任何帮助都将不胜感激。


问题在于Cython模块被编译为共享库,这些库无法通过“reload”函数重新加载。据我所知,目前你根本无法卸载共享库,因此你必须重新启动解释器。请注意,如果您使用Qt控制台,则可以避免重新启动* ipython *:只需使用“Ctrl +。”仅重新启动内核,而不重新启动整个控制台即可。 - Bakuriu
1个回答

41

我发现 "pyximport.install" 函数中有一个文档不完整的特性,可以允许重新加载Cython模块。将此特性设置为True后,您可以在不必重新启动Python的情况下以交互方式加载/重载Cython模块。

如果您使用以下代码初始化Cython模块:

import pyximport
pyximport.install(reload_support=True)
import my_functions as mf

您可以对Cython模块进行更改,然后使用以下方法重新加载:

reload(mf)

希望这对某人有用。


很棒。有人知道为什么它不是默认设置吗? - daknowles
2
如果有帮助的话:由于某种原因,我必须先执行reload(mf),然后再第二次导入my_functions as mf,才能使其更新。但是这样做之后它就可以正常工作了。 - N. Virgo
1
我正在尝试使用这个来重新加载新版本的.SO文件,但似乎没有起作用。在我的Python提示符中,我执行了import pyximport; pyximport.install(reload_support=True); import my_module as m。如果我用一个新的.SO文件替换旧的,并尝试reload(m),它仍然使用旧的文件。有什么办法可以让它工作? - Vinayak
@SalvatoreCosentino 我没能让它工作,所以最终我将我的程序分成了两个不同的部分。一个不变的部分只是导入.SO文件并在其中运行一个函数,而.SO文件则包含核心逻辑。不变的脚本检查更新,当发现更新的.SO文件时,下载它,替换现有的.SO文件并重新启动自己。当没有发现更新时,它会导入.SO文件并运行其中的一个函数。这种方法在Windows和OSX上都对我有效。 - Vinayak
谢谢@Vinayak。在我的情况下,我暂时放弃了REPL,而是运行一个测试脚本,在需要时编译Cython代码。 - Salvatore Cosentino
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接