繁体   English   中英

从自身内部重新启动 python-script

[英]Restart python-script from within itself

我有一个基于 python 的 GTK 应用程序,它加载了几个模块。 它从(linux)终端运行,如下所示:

./myscript.py --some-flag setting

用户可以从程序中下载(使用 Git)较新的版本。 如果存在/已下载,则会出现一个按钮,我希望使用新编译的内容(包括依赖项/导入)重新启动程序。 最好它还使用sys.argv的内容重新启动它,以保持所有标志不变。

所以我找不到/需要的是一个很好的重启过程,它会杀死程序的当前实例并使用相同的 arguments 启动一个新实例。

该解决方案最好也适用于 Windows 和 Mac,但这不是必需的。

您正在寻找os.exec*()

我认为这是一个更为详尽的答案,因为有时您可能会遇到太多打开的文件对象和描述符,这可能导致内存问题或与网络设备的并发连接。

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.get_open_files() + p.connections():
            os.close(handler.fd)
    except Exception, e:
        logging.error(e)

    python = sys.executable
    os.execl(python, python, *sys.argv)

对我来说,这部分就像一个魅力:

def restart():
    import sys
    print("argv was",sys.argv)
    print("sys.executable was", sys.executable)
    print("restart now")

    import os
    os.execv(sys.executable, ['python'] + sys.argv)

更新-上述答案的示例,以供将来参考

我有runme.sh

#!/bin/bash
kill -9 server.py
python /home/sun/workspace/c/src/server.py &

而且我在server.py中需要重新启动应用程序本身,所以我有:

os.system('runme.sh')

但这并没有通过遵循runme.sh重新启动应用程序本身,因此当我使用这种方式时:

os.execl('runme.sh', '')

然后我能够重新启动自己

我知道此解决方案从技术上讲并不是您要的,但是如果您想100%确保释放所有内容或不想依赖依赖项,则可以从另一个循环中运行脚本:

import os, time

while 1:
    os.system("python main.py")
    print "Restarting..."
    time.sleep(0.2) # 200ms to CTR+C twice

然后,您可以像下面这样简单地重新启动main.py:

quit()

我对#s3niOr的代码有了一点改进。

就我而言,python文件的路径中有空格。 因此,通过添加适当的格式,可以解决该问题。

请注意,在我的情况下,我的python文件没有其他参数。 因此,如果确实有其他论点,则必须处理它们。

这解决了重新启动路径中带有空格的python脚本的问题:

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.get_open_files() + p.connections():
            os.close(handler.fd)
    except Exception, e:
        logging.error(e)

    python = sys.executable
    os.execl(python, python, "\"{}\"".format(sys.argv[0]))

在Windows上运行(无args)

os.startfile(__file__)
sys.exit()

要么

os.startfile(sys.argv[0])
sys.exit()

用 Windows 试试这个工作:

当你想重新启动脚本调用这个 function

import os
def rest():
    os.system('cls')
    script_name = os.path.basename(__file__)
    os.system(script_name)

受到@YumYumYum的启发,并使用restart.sh和os.execl解决了该问题

restart.sh

#!/bin/bash/
pkill -f main.py
python main.py

将此添加到您的main.py

os.excel("restart.sh","")

我正在使用它为用户提供一个选项,以在控制台内重新启动脚本。 希望对您有所帮助。

def close_restart(self,csvfile):

    choice = input('Do you want to restart the program? Please select \'Y\' if you would like to restart.')

    if choice == 'Y' or choice == 'y':
        print('Restarting now...')
        os.execl(sys.executable, sys.executable, *sys.argv)

    else:
        print('Thank you for using the tool!')
        print('The program will close in 10s...')
        time.sleep(10)

因此,用户可以输入选项“是/否”来重新启动程序。

我一直在寻找解决方案,但没有发现任何可用于任何堆栈溢出帖子的东西。 也许某些答案已经过时,例如os.system已被子进程替换。 我在使用python 3的linux lubuntu 17.10上。

有两种方法对我有用。 两者都打开一个新的Shell窗口并在其中运行main.py脚本,然后关闭旧的。

1.将main.py与.sh脚本一起使用。

改编自@YumYumYum方法。 我不需要kill选项(尽管无论如何它都没有按名称杀死我的python进程,并且在测试时我不得不使用killall python3来实现它)。

我使用lxterminal但您可能会使用任何一个。

在名为restart.sh的文件中(使用chmod + x使其可执行)

#!/bin/bash

lxterminal -e python3 /home/my/folder/main.py &

然后在main.py中需要调用它时使用它

import subprocess

subprocess.run('/home/my/folder/restart.sh', shell=True)
quit()

2.从main.py内部

改编自@Stuffe方法。 该脚本位于main.py脚本的内部,并打开一个新的Shell窗口,然后运行新的脚本,然后退出旧脚本。 我不确定它是否需要time.sleep延迟,但是我还是使用了它。

import subprocess, time

cmd = 'python3 /home/my/folder/main.py'
subprocess.run('lxterminal -e ' + cmd, shell=True)   
time.sleep(0.2)
quit()

旧的答案使用exec<\/code>很好,但从长远来看是不可扩展的。 还有一种主\/从进程关系或后台守护程序\/服务的方法,它们将监视更改,但主要是特定于操作系统的,甚至在同一操作系统系列(init.d vs systemd vs)之间也不同。

通过使用引导技术和简单的subprocess.Popen()<\/code>调用还有一个中间立场,因此假设启动原始程序的用户有权运行可执行文件(例如\/usr\/bin\/python<\/code> )也应该在没有的情况下工作由于使用完全相同的可执行文件而导致的任何权限错误。 引导,因为它是创建和调用重启程序的主程序,也就是在初始启动后通过自己的引导程序拉动自己。

所以一个简单的程序(重新)启动器可以这样写,如其他答案中所写:

from subprocess import Popen
from time import sleep

def main():
    sleep(<delay>)
    Popen([<executable path>, *<list of argv>], cwd=<cwd path>)

if __name__ == "__main__":
    main()
os.execv(sys.executable, ['python3'] + sys.argv)

我这样做如下:

    def restartApp(self):
        python = sys.executable
        os.execl(python, python, *sys.argv)

而不是这个:

from os import execl
from sys import executable, executable, argv
execl(executable, executable, *argv)

...,这也很好,我决定自己做:

rerun.sh:
#!/bin/bash
killall python
python project.py

project.py:
system('bash rerun.sh')
  1. 在正确的位置,从 my.py 项目中的 OC package 调用 System。
  2. 由于 py-file 和 sh 在同一个文件夹中,因此我没有指定路径:我从包含的程序列表中删除应用程序文件,因为我的程序没有自己的应用程序文件名,所以它总是替换为Python厂名; 然后我将开始我的新程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM