python3.7 中的模块重新加载如何工作?
How does module reload in python3.7 work?
如何在 python 3.7.1 中重新加载模块?
设置和总结
我是 运行 python 3.7.1 Linux。我正在开发一个 C 模块,一旦更改,重新加载模块会非常方便。我关注了 How do I unload (reload) a Python module?,但我无法让它在这个环境中工作。
为了演示我的问题,我根据教程中的 SPAM 示例编写了一个简单的模块,returns 模块的构建时间。它永远不会重新加载。
代码
实施是教程中的垃圾邮件示例。它有一个函数 hello,returns 构建时间:
return Py_BuildValue("s", __TIME__);
我正在使用以下 python 脚本进行编译和加载:
import os
import helloworld
print(helloworld.hello('test'))
os.system("touch helloworld.c")
os.system("python3 setup.py build")
os.system("python3 setup.py install --user")
from importlib import reload
helloworld=reload(helloworld)
print(helloworld.hello('test'))
导入模块,摸主文件,编译安装,然后重新加载。
输出
模块应该在重新加载后显示新的编译时间,但输出没有改变(我省略了一些调试信息,输出是 first/last 行,08:04:20):
python driver.py
08:04:20
running build
running build_ext
building 'helloworld' extension
gcc ...
running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-3.7/helloworld.cpython-37m-x86_64-linux-gnu.so -> /home/wuebbel/.local/lib/python3.7/site-packages
running install_egg_info
Removing /home/wuebbel/.local/lib/python3.7/site-packages/HelloWorld-2.1-py3.7.egg-info
Writing /home/wuebbel/.local/lib/python3.7/site-packages/HelloWorld-2.1-py3.7.egg-info
08:04:20
运行 脚本再次加载正确的模块并显示新时间:
wuebbel@02e267406db3:~/Projekte/Mandelbrot Demos/helloworld$ python driver.py
08:16:58
...
08:16:58
我的模块似乎永远不会重新加载。这样做的正确方法是什么?
我怀疑重新加载包含编译代码的模块的可行性,阅读这个答案: which suggests that PEP 489 changed module reloading (between python 3.6 and 3.7), possibly "breaking" shared重新加载库。
Due to limitations in shared library loading (both dlopen on POSIX and LoadModuleEx on Windows), it is not generally possible to load a modified library after it has changed on disk.
这可以解释您遇到的问题。
如果这是一个操作案例,我建议您有一个创建包的主 python 程序,然后使用单独的 python 进程来加载它。
subprog.py:
import helloworld
print(helloworld.hello('test'))
master.py
import os,subprocess,sys
def runit():
subprocess.run([sys.executable,os.path.join(os.path.dirname(__file__),"subprog.py")])
runit()
os.system("touch helloworld.c")
os.system("python3 setup.py build")
os.system("python3 setup.py install --user")
runit()
使用 sys.executable
确保相同的 python 可执行文件用于主 python 进程和子进程,因此更加透明。
如何在 python 3.7.1 中重新加载模块?
设置和总结
我是 运行 python 3.7.1 Linux。我正在开发一个 C 模块,一旦更改,重新加载模块会非常方便。我关注了 How do I unload (reload) a Python module?,但我无法让它在这个环境中工作。
为了演示我的问题,我根据教程中的 SPAM 示例编写了一个简单的模块,returns 模块的构建时间。它永远不会重新加载。
代码
实施是教程中的垃圾邮件示例。它有一个函数 hello,returns 构建时间:
return Py_BuildValue("s", __TIME__);
我正在使用以下 python 脚本进行编译和加载:
import os
import helloworld
print(helloworld.hello('test'))
os.system("touch helloworld.c")
os.system("python3 setup.py build")
os.system("python3 setup.py install --user")
from importlib import reload
helloworld=reload(helloworld)
print(helloworld.hello('test'))
导入模块,摸主文件,编译安装,然后重新加载。
输出
模块应该在重新加载后显示新的编译时间,但输出没有改变(我省略了一些调试信息,输出是 first/last 行,08:04:20):
python driver.py
08:04:20
running build
running build_ext
building 'helloworld' extension
gcc ...
running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-3.7/helloworld.cpython-37m-x86_64-linux-gnu.so -> /home/wuebbel/.local/lib/python3.7/site-packages
running install_egg_info
Removing /home/wuebbel/.local/lib/python3.7/site-packages/HelloWorld-2.1-py3.7.egg-info
Writing /home/wuebbel/.local/lib/python3.7/site-packages/HelloWorld-2.1-py3.7.egg-info
08:04:20
运行 脚本再次加载正确的模块并显示新时间:
wuebbel@02e267406db3:~/Projekte/Mandelbrot Demos/helloworld$ python driver.py
08:16:58
...
08:16:58
我的模块似乎永远不会重新加载。这样做的正确方法是什么?
我怀疑重新加载包含编译代码的模块的可行性,阅读这个答案:
Due to limitations in shared library loading (both dlopen on POSIX and LoadModuleEx on Windows), it is not generally possible to load a modified library after it has changed on disk.
这可以解释您遇到的问题。
如果这是一个操作案例,我建议您有一个创建包的主 python 程序,然后使用单独的 python 进程来加载它。
subprog.py:
import helloworld
print(helloworld.hello('test'))
master.py
import os,subprocess,sys
def runit():
subprocess.run([sys.executable,os.path.join(os.path.dirname(__file__),"subprog.py")])
runit()
os.system("touch helloworld.c")
os.system("python3 setup.py build")
os.system("python3 setup.py install --user")
runit()
使用 sys.executable
确保相同的 python 可执行文件用于主 python 进程和子进程,因此更加透明。