2011-01-09 13 views
26

Tenía curiosidad de cómo se puede ejecutar una secuencia de comandos python en segundo plano, repitiendo una tarea cada 60 segundos. Sé que puedes poner algo en segundo plano usando &, ¿es eso efectivo para este caso?Efficient Python Daemon

Estaba pensando en hacer un ciclo, tener que esperar 60 segundos y volver a cargarlo, pero algo se siente mal al respecto.

+1

Depende de lo que quiera. Si desea programar una tarea para que se repita de vez en cuando, eche un vistazo a cron. – Falmarri

Respuesta

7

Creo que su idea es más o menos exactamente lo que quiere. Por ejemplo:

import time 

def do_something(): 
    with open("/tmp/current_time.txt", "w") as f: 
     f.write("The time is now " + time.ctime()) 

def run(): 
    while True: 
     time.sleep(60) 
     do_something() 

if __name__ == "__main__": 
    run() 

La llamada a time.sleep(60) pondrá su programa para dormir durante 60 segundos. Cuando se acabe ese tiempo, el sistema operativo activará su programa y ejecutará la función do_something(), luego lo pondrá nuevamente en modo de suspensión. Mientras su programa está durmiendo, no está haciendo nada de manera muy eficiente. Este es un patrón general para escribir servicios en segundo plano.

Para ejecutar esta realidad desde la línea de comandos, puede utilizar &:

$ python background_test.py & 

Al hacer esto, cualquier salida del script irá a la misma terminal como la que lo inició a partir. Puede redirigir la salida para evitar esto:

$ python background_test.py >stdout.txt 2>stderr.txt & 
+0

Gracias, hombre, esto es exactamente lo que estaba buscando. ¡Los bits y las piezas de la programación que conozco vienen de Javascript e intentar hacer cualquier cosa con un temporizador se convirtió en una pesadilla! –

+1

Es posible que también desee ver nohup (por ejemplo, 'nohup python background_test.py') suponiendo que desea que el daemon siga funcionando después de cerrar la sesión) – Foon

+1

Hay una manera más fácil de hacerlo utilizando' python-daemon' que es el "biblioteca de procesos daemon estándar": http://stackoverflow.com/a/8375012/462302 – aculich

5

Usando & en la cáscara es probablemente la forma más sencilla muertos como Greg describe.

Si realmente desea crear un poderoso Daemon, necesitará examinar el comando os.fork().

El ejemplo de Wikipedia:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import os, time 

def createDaemon(): 
    """ 
     This function create a service/Daemon that will execute a det. task 
    """ 

    try: 
    # Store the Fork PID 
    pid = os.fork() 

    if pid > 0: 
     print 'PID: %d' % pid 
     os._exit(0) 

    except OSError, error: 
    print 'Unable to fork. Error: %d (%s)' % (error.errno, error.strerror) 
    os._exit(1) 

    doTask() 

def doTask(): 
    """ 
     This function create a task that will be a daemon 
    """ 

    # Open the file in write mode 
    file = open('/tmp/tarefa.log', 'w') 

    # Start the write 
    while True: 
    print >> file, time.ctime() 
    file.flush() 
    time.sleep(2) 

    # Close the file 
    file.close() 

if __name__ == '__main__': 

    # Create the Daemon 
    createDaemon() 

Y entonces se puede poner cualquier tarea que necesita dentro del bloque doTask().

Usted no necesita poner en marcha esta usando &, y sería permitirá personalizar la ejecución de un poco más lejos.

83

En lugar de escribir su propio daemon, ¡use python-daemon en su lugar! python-daemon implementa la especificación de daemon de buen comportamiento de PEP 3143, "Biblioteca de procesos daemon estándar".

He incluido código de ejemplo basado en la respuesta aceptada a esta pregunta, ya pesar de que el código se ve casi idéntica, que cuenta con una importante diferencia fundamental. Sin python-daemon que tendría que utilizar & para poner su proceso en segundo plano y nohup y para mantener su proceso de perder la vida al salir de su concha. En cambio, este se desconectará automáticamente de su terminal cuando ejecute el programa.

Por ejemplo:

import daemon 
import time 

def do_something(): 
    while True: 
     with open("/tmp/current_time.txt", "w") as f: 
      f.write("The time is now " + time.ctime()) 
     time.sleep(5) 

def run(): 
    with daemon.DaemonContext(): 
     do_something() 

if __name__ == "__main__": 
    run() 

Para realmente ejecutarlo:

python background_test.py 

y la nota la ausencia de & aquí.

Además, this other stackoverflow answer explica en detalle los muchos beneficios del uso de python-daemon.

+1

Estaría sorprendido, pero el autor de PEP y autor de la biblioteca es la misma persona. Así que sí, la biblioteca implementa muy bien ese PEP :) – Reishin

+0

Usted dice "esta otra respuesta stackoverflow", pero el enlace a una pregunta, no una respuesta. La respuesta seleccionada a la pregunta a la que se vincula no usa (en el momento de este comentario) python-daemon. ¿Quizás te refieres a https://stackoverflow.com/a/688448/117471? –