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.
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).
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.)
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.
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.
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).
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()
Vous pouvez utiliser reload (module) pour recharger un module.
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