我有一个 python 程序,它在运行之前加载了相当多的数据。因此,我希望能够在不重新加载数据的情况下重新加载代码。使用普通的python,importlib.reload一直工作正常。下面是一个例子:
设置.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
extensions = [
Extension("foo.bar", ["foo/bar.pyx"],
language="c++",
extra_compile_args=["-std=c++11"],
extra_link_args=["-std=c++11"])
]
setup(
name="system2",
ext_modules=cythonize(extensions, compiler_directives={'language_level' : "3"}),
)
Run Code Online (Sandbox Code Playgroud)
foo/bar.py
cpdef say_hello():
print('Hello!')
Run Code Online (Sandbox Code Playgroud)
跑步者.py:
import pyximport
pyximport.install(reload_support=True)
import foo.bar
import subprocess
from importlib import reload
if __name__ == '__main__':
def reload_bar():
p = subprocess.Popen('python setup.py build_ext --inplace',
shell=True,
cwd='<your directory>')
p.wait()
reload(foo.bar)
foo.bar.say_hello()
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用。如果我编辑 bar.pyx 并运行,reload_bar我看不到我的更改。我也尝试过pyximport.build_module(),但没有运气 - 模块重建但没有重新加载。我在“普通”python shell 中运行,而不是在 IPython 中运行,如果它有所不同的话。
我能够得到一个适用于 Python 2.xa 的解决方案比 Python 3.x 容易得多。无论出于何种原因,Cython 似乎正在缓存.so它从中导入模块的可共享对象 ( ) 文件,即使在运行时重建和删除旧文件后,它仍然从旧的可共享对象文件中导入。然而,这无论如何都不是必需的(当你import foo.bar,它不会创建一个),所以我们可以跳过这个。
最大的问题是即使在reloading之后,python 仍然保留对旧模块的引用。正常的 python 模块似乎可以找到,但与 cython 无关。为了解决这个问题,我运行执行两个语句来代替reload(foo.bar)
del sys.modules['foo.bar']
import foo.bar
Run Code Online (Sandbox Code Playgroud)
这成功地(尽管可能效率较低)重新加载了 cython 模块。运行该子进程的 Python 3.x 中唯一存在的问题会创建有问题的可共享对象。相反,一起跳过所有这些,让模块import foo.bar发挥其魔力pyximporter,然后为您重新编译。我还在pyxinstall命令中添加了一个选项来指定语言级别以匹配您在setup.py
pyximport.install(reload_support=True, language_level=3)
Run Code Online (Sandbox Code Playgroud)
所以大家一起:
跑步者.py
import sys
import pyximport
pyximport.install(reload_support=True, language_level=3)
import foo.bar
if __name__ == '__main__':
def reload_bar():
del sys.modules['foo.bar']
import foo.bar
foo.bar.say_hello()
input(" press enter to proceed ")
reload_bar()
foo.bar.say_hello()
Run Code Online (Sandbox Code Playgroud)
其他两个文件保持不变
跑步:
Hello!
press enter to proceed
Run Code Online (Sandbox Code Playgroud)
-replace"Hello!"在富/ bar.pyx用"Hello world!",并按Enter。
Hello world!
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1295 次 |
| 最近记录: |