Reiniciando un script de python auto-actualizado

He escrito un script que se mantendrá actualizado descargando la última versión de un sitio web y sobrescribiendo el script en ejecución.

No estoy seguro de cuál es la mejor manera de reiniciar el script después de que se haya actualizado.

¿Algunas ideas?

Realmente no quiero tener un script de actualización separado. Ah, y tiene que funcionar en ambos linux / windows también.

En Linux, o cualquier otra forma de Unix, os.execl y amigos son una buena opción para esto, solo necesita volver a ejecutar sys.executable con los mismos parámetros con los que se ejecutó la última vez ( sys.argv , más o menos) o cualquier variante de la misma si necesita informar a su próxima encarnación que en realidad es un reinicio. En Windows, os.spawnl (y amigos) es lo mejor que puedes hacer (aunque tomará más tiempo y memoria que os.execl y amigos durante la transición).

El proyecto CherryPy tiene un código que se reinicia. Así es como lo hacen :

  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) 

He usado esta técnica en mi propio código, y funciona muy bien. (No me molesté en realizar el paso de cita de argumentos en las ventanas anteriores, pero probablemente sea necesario si los argumentos pueden contener espacios u otros caracteres especiales).

Creo que la mejor solución debería ser algo como esto:

Su progtwig 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") 

El script de actualización: (por ejemplo: 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") 

Espero que esto ayude.

¡La solución más limpia es un script de actualización separado!

Ejecute su progtwig dentro de él, informe (al salir) que hay una nueva versión disponible. Esto permite que su progtwig guarde todos sus datos, el actualizador aplique la actualización y ejecute la nueva versión, que luego carga los datos guardados y continúa. Para el usuario, esto puede ser completamente transparente, ya que simplemente ejecutan el shell de actualización que ejecuta el progtwig real.

El equipo de pocoo tiene un recargador muy bueno para su servidor de desarrollo dentro de werkzueg. Verifique el código aquí (es hacia la parte inferior del archivo).

Puede usar recargar (módulo) para recargar un módulo.

Archivo principal:

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

Actualizar archivo:

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

Aquí está la lógica:

El progtwig principal llama a la función de actualización

1) Si la función de actualización necesita actualizarse, entonces se actualiza y llama a nuevas instancias de “main”

Luego sale la instancia original de “main”.

2) Si la función de actualización no necesita actualizarse, entonces “main” continúa ejecutándose

Para admitir adicionalmente las llamadas de script con el parámetro “-m” de Python, se puede usar lo siguiente (basado en la respuesta de Alex; versión de 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()