Перезапустите python- script изнутри самого себя

У меня есть приложение GTK на основе python, которое загружает несколько модулей. Он запускается с терминала (linux) следующим образом:

./myscript.py --some-flag setting

Внутри программы пользователь может загрузить (используя Git) новые версии. Если такое существует/загружено, появляется кнопка, которая, как мне хотелось бы, перезапустила бы программу с недавно скомпилированным содержимым (включая зависимости/импорт). Предпочтительно он также перезапускает его, используя содержимое sys.argv, чтобы сохранить все флаги такими, какими они были.

Так что я не могу найти/нужна хорошая процедура перезапуска, которая убивает текущий экземпляр программы и запускает новый, используя те же аргументы.

Предпочтительно, решение должно работать и для Windows и Mac, но это не существенно.

Ответы

Ответ 2

Я думаю, что это более сложный ответ, так как иногда у вас может быть слишком много открытых файловых объектов и дескрипторов, которые могут вызвать проблемы с памятью или параллельные подключения к сетевому устройству.

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)

Ответ 3

UPDATE - из приведенного выше ответа с некоторым примером для дальнейшего использования

У меня 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', '')

Затем я смог перезапустить себя

Ответ 4

Я знаю, что это решение технически не является то, о чем вы просите, но если вы хотите быть на 100% уверенным, что вы освободили все или не хотите полагаться на зависимости, вы можете просто запустить script из цикла в другой:

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

Я немного улучшил код # 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

Работает на Windows (без аргументов)

os.startfile(__file__)
sys.exit()

ИЛИ ЖЕ

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

Ответ 7

Вдохновлен @YumYumYum и исправил проблему с помощью restart.sh и os.execl

restart.sh

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

Добавьте это в ваш main.py

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

Ответ 8

Я использую это, чтобы дать возможность пользователям перезапустить скрипт в консоли. Надеюсь, это поможет.

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)

Таким образом, пользователь может ввести опцию "Y/N", чтобы перезапустить программу или нет.