从脚本内部重新启动Python脚本
从脚本内部重新启动Python脚本
我有一个基于Python的GTK应用程序,它加载了几个模块。它在(Linux)终端中运行,如下所示:\n./myscript.py --some-flag setting
\n从程序内部,用户可以下载(使用Git)更新的版本。\n如果存在/已下载,将出现一个按钮,我希望能够使用新编译的内容(包括依赖/导入)重新启动程序。最好还可以使用sys.argv
的内容重新启动,以保持所有的标志不变。\n因此,我找不到/需要一个良好的重启过程,它可以终止当前实例的程序并使用相同的参数启动一个新的实例。\n最好的解决方案应该在Windows和Mac上都能工作,但这并非必需。
问题的出现原因是可能会出现过多的打开文件对象和描述符,这可能会导致内存问题或对网络设备的并发连接。解决方法是通过重新启动当前程序,并清理文件对象和描述符。
解决方法的代码如下:
import os import sys import psutil import logging def restart_program(): """Restarts the current program, with file objects and descriptors cleanup""" try: p = psutil.Process(os.getpid()) for handler in p.open_files() + p.connections(): os.close(handler.fd) except Exception as e: logging.error(e) python = sys.executable os.execl(python, python, *sys.argv)
如果使用的是psutil包的当前版本(5.4.8),则需要将`p.get_open_files()`更改为`p.open_files()`。
如果使用的是Python 3.6或更高版本,需要将`except Exception, e:`更改为`except Exception as e:`。
在运行过程中,可能会出现错误信息:`ERROR:root:[Errno 9] Bad file descriptor`。
在Python中,可以使用`os.exec*()`系列命令来重新启动一个Python脚本。要以与最初运行时相同的命令行参数重新启动当前程序,可以使用以下代码:
import os import sys os.execv(sys.argv[0], sys.argv)
这段代码将重新启动当前程序,并使用与最初运行时相同的命令行参数。
然而,这段代码在Python 2.7.9中会导致语法错误。这是因为命令中的星号是通配符,不应该被字面解释。实际上,有许多以"exec"开头的命令,你需要根据自己的使用情况选择正确的命令。可以参考链接中的文档以获取更多信息。不过,这里提供一些示例代码可能会有所帮助。
当出现权限错误(PermissionError: [Errno 13] Permission denied)时,需要为脚本添加执行权限才能使其正常工作。可以使用以下命令为脚本添加执行权限:
sudo chmod +x test.py
另一种替代方法是使用以下代码:
import os import sys os.execv(sys.executable, ['python'] + sys.argv)
这种方法不需要使用`chmod`(以避免出现权限被拒绝的错误),也不需要在脚本开头添加shebang(以避免出现OSError: [Errno 8] Exec format error)。
关于该方法是否正确关闭调用者的Python运行时,以及是否需要关闭父脚本的问题,目前没有明确的说明。
对于作为模块执行的脚本(例如`python -m path.to.module`),可以如何实现重新启动是一个需要考虑的问题。