从内部重启python-script

时间:2012-07-04 13:19:23

标签: python

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

./myscript.py --some-flag setting

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

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

此外,该解决方案最适用于Windows和Mac,但并不是必需的。

10 个答案:

答案 0 :(得分:33)

您正在寻找os.exec*()

答案 1 :(得分:20)

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

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)

答案 2 :(得分:2)

更新 - 上述答案中的一些示例供将来参考

我有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', '')

然后我能够重新启动

答案 3 :(得分:2)

对我来说,这部分很有魅力:

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)

我知道了 here

答案 4 :(得分:1)

我知道这个解决方案在技术上并不是你要求的,但是如果你想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()

答案 5 :(得分:1)

我对#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]))

答案 6 :(得分:1)

在Windows上工作 (无参数)

os.startfile(__file__)
sys.exit()

OR

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

答案 7 :(得分:0)

受@YumYumYum的启发并修复了问题 使用restart.sh和os.execl

restart.sh

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

将此添加到您的main.py

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

答案 8 :(得分:0)

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

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)

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

答案 9 :(得分:0)

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

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

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

改编自@YumYumYum方法。我不需要kill选项(尽管无论如何它都没有按名称杀死我的python进程,并且在测试时我不得不使用#!/bin/bash lxterminal -e python3 /home/my/folder/main.py & 来实现它)。

我使用lxterminal,但是您可以使用任何一个。

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

import subprocess

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

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

import subprocess, time

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

2。从main.py内部

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

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://some.url.com"
    android:layout_width="match_parent">

    <include
        layout="@layout/alarms_layout"
        android:layout_width="wrap_content"
        />

    <ImageView
        android:id="@+id/saved_files"
        android:layout_alignParentEnd="true"
        />

</RelativeLayout>