Herstart python-script vanuit zichzelf

Ik heb een op Python gebaseerde GTK-toepassing die verschillende modules laadt. Het wordt als volgt uitgevoerd vanaf de (linux) terminal:

./myscript.py --some-flag setting

Vanuit het programma kan de gebruiker nieuwere versies downloaden (met Git).
Als dergelijke bestaat/wordt gedownload, verschijnt er een knop waarvan ik zou willen dat deze het programma zou herstarten met nieuw gecompileerde inhoud (inclusief afhankelijkheden/importen). Bij voorkeur zou het het ook herstarten met de inhoud van sys.argv om alle vlaggen te behouden zoals ze waren.

Wat ik dus niet kan vinden/nodig heb, is een mooie herstartprocedure die de huidige instantie van het programma doodt en een nieuwe start met dezelfde argumenten.

Bij voorkeur zou de oplossing ook voor Windows en Mac moeten werken, maar het is niet essentieel.


Antwoord 1, autoriteit 100%

U zoekt naar os.exec*() reeks commando’s.

Om uw huidige programma opnieuw te starten met exact dezelfde opdrachtregelargumenten als het oorspronkelijk werd uitgevoerd, kunt u het volgende gebruiken:

os.execv(sys.argv[0], sys.argv)

Antwoord 2, autoriteit 66%

Ik denk dat dit een uitgebreider antwoord is, omdat je soms te veel open bestandsobjecten en descriptors krijgt, die geheugenproblemen of gelijktijdige verbindingen met een netwerkapparaat kunnen veroorzaken.

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)

Antwoord 3, autoriteit 7%

UPDATE – van het bovenstaande antwoord met een voorbeeld voor toekomstig gebruik

Ik heb runme.sh

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

En ik heb server.py waar ik de applicatie zelf opnieuw moet opstarten, dus ik had:

os.system('runme.sh')

maar dat heeft de applicatie zelf niet opnieuw opgestart door runme.sh te volgen, dus toen ik op deze manier gebruikte:

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

Toen kon ik zichzelf opnieuw opstarten


Antwoord 4, autoriteit 5%

Ik weet dat deze oplossing technisch niet is waar je om vraagt, maar als je er 100% zeker van wilt zijn dat je alles hebt vrijgemaakt of niet wilt vertrouwen op afhankelijkheden, kun je het script gewoon uitvoeren vanuit een lus in een andere:

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

Vervolgens kunt u main.py zo eenvoudig herstarten als:

quit()

Antwoord 5, autoriteit 4%

Werkt bij Windows
(Zonder argumenten)

os.startfile(__file__)
sys.exit()

OF

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

Antwoord 6, autoriteit 4%

Voor mij werkte dit onderdeel als een tierelier:

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)

Ik heb het hier.


Antwoord 7, autoriteit 2%

Ik heb een kleine verbetering van de code van #s3niOr.

In mijn geval zijn er spaties in het pad van het python-bestand. Dus door een juiste opmaak toe te voegen, kan het probleem worden opgelost.

Merk op dat in mijn geval mijn python-bestand geen andere argumenten heeft. Dus als je andere argumenten hebt, moet je die oplossen.

Dit lost het probleem op van het herstarten van een python-script dat spaties in zijn pad heeft:

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]))

Antwoord 8, autoriteit 2%

Ik was op zoek naar een oplossing hiervoor en vond niets dat werkt op een van de stapeloverloopposten. Misschien zijn sommige antwoorden te verouderd, b.v. os.system is vervangen door subproces. Ik gebruik linux lubuntu 17.10 en gebruik python 3.

Twee methoden werkten voor mij. Beiden openen een nieuw shell-venster en voeren het main.py-script erin uit en sluiten vervolgens de oude.

1. Main.py gebruiken met een .sh-script.

Aangepast van de @YumYumYum-methode. Ik had de kill-optie niet nodig (hoewel het mijn python-proces sowieso niet bij naam heeft gedood en ik killall python3 moest gebruiken om het te bereiken tijdens het testen).

Ik gebruik lxterminal, maar je zou er waarschijnlijk een kunnen gebruiken.

In het bestand genaamd restart.sh (chmod +x om het uitvoerbaar te maken)

#!/bin/bash
lxterminal -e python3 /home/my/folder/main.py &

Gebruik dit dan in de main.py wanneer je het moet aanroepen

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

2. Vanuit main.py

Aangepast van de @Stuffe-methode. Deze is intern in het main.py-script en opent een nieuw shell-venster, voert vervolgens het nieuwe script uit en sluit vervolgens het oude script af. Ik weet niet zeker of het de tijd nodig heeft. Slaapvertraging, maar ik heb het toch gebruikt.

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

Antwoord 9

Geïnspireerd door @YumYumYum en het probleem opgelost
Herstart.sh en os.execl gebruiken

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

Voeg dit toe aan uw main.py

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

Antwoord 10

Ik gebruik dit om de gebruikers een optie te geven om het script binnen de console opnieuw te starten. Ik hoop dat het een hulp kan zijn.

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)

De gebruiker kan dus een optie ‘J/N’ invoeren om het programma al dan niet te herstarten.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes