web-dev-qa-db-fra.com

Redémarrage d'un script à mise à jour automatique python

J'ai écrit un script qui se tiendra à jour en téléchargeant la dernière version à partir d'un site Web et en écrasant le script en cours d'exécution.

Je ne sais pas quelle est la meilleure façon de redémarrer le script après sa mise à jour.

Des idées?

Je ne veux pas vraiment avoir un script de mise à jour séparé. oh et cela doit aussi fonctionner sur linux/windows.

41
Ashy

Sous Linux, ou toute autre forme d'unix, os.execl et les amis sont un bon choix pour cela - il vous suffit de ré-exécuter sys.executable avec le même paramètres avec lesquels il a été exécuté la dernière fois (sys.argv, plus ou moins) ou toute variante de celui-ci si vous devez informer votre prochaine incarnation qu'il s'agit en fait d'un redémarrage. Sous Windows, os.spawnl (et amis) est à peu près le meilleur que vous puissiez faire (bien que cela prendra temporairement plus de temps et de mémoire que os.execl et ses amis pendant la transition).

30
Alex Martelli

Le projet CherryPy a un code qui redémarre lui-même. Voici comment ils le font :

    args = sys.argv[:]
    self.log('Re-spawning %s' % ' '.join(args))

    args.insert(0, sys.executable)
    if sys.platform == 'win32':
        args = ['"%s"' % arg for arg in args]

    os.chdir(_startup_cwd)
    os.execv(sys.executable, args)

J'ai utilisé cette technique dans mon propre code, et cela fonctionne très bien. (Je n'ai pas pris la peine de faire l'étape de citation d'argument sur les fenêtres ci-dessus, mais c'est probablement nécessaire si les arguments peuvent contenir des espaces ou d'autres caractères spéciaux.)

18
Josh

Je pense que la meilleure solution serait quelque chose comme ceci:

Votre programme normal:

...

# ... part that downloaded newest files and put it into the "newest" folder

from subprocess import Popen

Popen("/home/code/reloader.py", Shell=True) # start reloader

exit("exit for updating all files")

Le script de mise à jour: (par exemple: home/code/reloader.py)

from shutil import copy2, rmtree
from sys import exit

# maybie you could do this automatic:
copy2("/home/code/newest/file1.py", "/home/code/") # copy file
copy2("/home/code/newest/file2.py", "/home/code/")
copy2("/home/code/newest/file3.py", "/home/code/")
...

rmtree('/home/code/newest') # will delete the folder itself

Popen("/home/code/program.py", Shell=True) # go back to your program

exit("exit to restart the true program")

J'espère que cela t'aidera.

5
Joschua

La solution la plus propre est un script de mise à jour séparé!

Exécutez votre programme à l'intérieur, signalez (à la sortie) qu'une nouvelle version est disponible. Cela permet à votre programme d'enregistrer toutes ses données, au programme de mise à jour d'appliquer la mise à jour et d'exécuter la nouvelle version, qui charge ensuite les données enregistrées et continue. Pour l'utilisateur, cela peut être complètement transparent, car ils exécutent simplement le programme de mise à jour-Shell qui exécute le vrai programme.

2
Roger Pate

L'équipe pocono a un très bon rechargeur pour son serveur de développement à l'intérieur de werkzeug. Vérifiez le code ici (c'est vers le bas du fichier).

1
Bryan McLemore

Pour prendre en charge en outre les appels de script avec le paramètre "-m" de Python, les éléments suivants peuvent être utilisés (en fonction de la réponse d'Alex; version Windows):

os.spawnl(os.P_WAIT, sys.executable, *([sys.executable] +
    (sys.argv if __package__ is None else ["-m", __loader__.name] + sys.argv[1:])))
sys.exit()
1
sevenforce

Vous pouvez utiliser reload (module) pour recharger un module.

0
Alexandru

Fichier principal:

if __name__ == '__main__':

if os.path.isfile('__config.py'):
    print 'Development'
    Push.update_server()
else:
    e = update.check()
    if not e: sys.exit()

Fichier de mise à jour:

def check():
    e = 1.....perform checks, if something needs updating, e=0;
    if not e:
        os.system("python main.pyw")
    return e

Voici la logique:

Le programme principal appelle la fonction de mise à jour

1) Si la fonction de mise à jour doit être mise à jour, elle met à jour et appelle de nouvelles instances de "main"

Ensuite, l'instance d'origine de "principal" quitte.

2) Si la fonction de mise à jour n'a pas besoin d'être mise à jour, alors "main" continue de s'exécuter

0
takrliu