2009-11-17 20 views
30

He escrito una secuencia de comandos que se mantendrá actualizada al descargar la última versión de un sitio web y sobrescribir el script en ejecución.Reinicio de una secuencia de comandos python autoactualizable

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

¿Alguna idea?

Realmente no quiero tener un script de actualización separado. oh y tiene que funcionar tanto en Linux como en Windows.

Respuesta

26

En Linux, o cualquier otra forma de Unix, os.execl y amigos son una buena opción para esto - sólo tiene que volver a exec sys.executable con los mismos parámetros que se ejecutó con la última vez (sys.argv, más o menos) o cualquier variante del mismo 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 puede hacer (aunque transitoriamente llevará más tiempo y memoria que os.execl y amigos durante la transición).

+0

Probablemente la mejor manera de hacerlo si el script es lo suficientemente simple. –

+0

os.execl funciona en Windows, también. – Josh

+23

One-liner para futura referencia: 'os.execl (sys.executable, * ([sys.executable] + sys.argv))' – Claudiu

1

El equipo de pocoo tiene un recargador muy bueno para su servidor de desarrollo dentro de werkzueg. Compruebe el código here (está hacia la parte inferior del archivo).

+0

Ese enlace está ahora muerto. Hay otro? – Glycerine

+0

Parece que se movieron a github: [werkzeug/serving.py] (https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/serving.py) – johnny

+0

¡Gracias! Actualizado el enlace –

2

¡La solución más limpia es una secuencia de comandos de actualización por separado!

Ejecute su programa dentro de él, informe (al salir) que hay una nueva versión disponible. Esto le permite a su programa guardar todos sus datos, el actualizador para aplicar la actualización y ejecutar la nueva versión, que luego carga los datos guardados y continúa. Para el usuario, esto puede ser completamente transparente, ya que solo ejecuta el shell de actualización que ejecuta el programa real.

+0

Entonces no puede actualizar el script de actualización. – JDiMatteo

+0

Puede, use su programa principal para buscar actualizaciones. Cuando hay una nueva actualización disponible. descarga un nuevo 'update.py' ... luego ejecútalo. 'update.py' cerrará la instancia anterior y generará una nueva. – Harvey

3

creo que la mejor solución whould ser algo como esto:

su programa normal de:

... 

# ... 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: inicio/código/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 te ayude.

15

El proyecto CherryPy tiene un código que se reinicia. Aquí es how they do it:

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 utilizado esta técnica en mi propio código, y funciona muy bien. (No me molesté en hacer el paso para citar argumentos en las ventanas de arriba, pero probablemente sea necesario si los argumentos pueden contener espacios u otros caracteres especiales.)

0

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

archivo de actualización:

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

Ésta es la lógica:

programa principal llama a la función de actualización

1) Si la actualización la función necesita actualizar, que upd ates y llama a una instancia nueva de "main"

Luego sale la instancia original de "main".

2) Si la función de actualización no tiene que actualizar, a continuación, "principal" sigue funcionando

0

Para apoyar adicionalmente script llama con "m" de Python parámetro la siguiente puede ser utilizado (basado en la respuesta del 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() 
Cuestiones relacionadas