2011-01-09 43 views
26

Ero curioso di sapere come è possibile eseguire uno script python in background, ripetendo un'attività ogni 60 secondi. So che puoi mettere qualcosa in sottofondo usando &, questo è effettivamente efficace per questo caso?Efficient Python Daemon

Stavo pensando di fare un ciclo, di averlo aspettato per 60 secondi e di averlo caricato di nuovo, ma qualcosa non va.

+1

Dipende da ciò che si desidera. Se vuoi programmare un'attività da ripetere ogni tanto, dai un'occhiata a cron. – Falmarri

risposta

7

Penso che la tua idea sia esattamente ciò che desideri. Per esempio:

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 chiamata a time.sleep(60) metterà il vostro programma di dormire per 60 secondi. Quando il tempo è scaduto, il sistema operativo attiva il programma ed esegue la funzione do_something(), quindi la riporta in stato di stop. Mentre il tuo programma sta dormendo, non sta facendo nulla in modo molto efficiente. Questo è un modello generale per la scrittura di servizi in background.

Per eseguire in realtà questo dalla riga di comando, è possibile utilizzare &:

$ python background_test.py & 

Nel fare questo, qualsiasi uscita dallo script andrà allo stesso terminale, come quella di partenza da. È possibile reindirizzare l'uscita per evitare questo:

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

Grazie amico, questo è esattamente quello che stavo cercando. I pezzi di programmazione che conosco provengono da Javascript e cercano di fare qualsiasi cosa su un timer che si è trasformato in un incubo! –

+1

Si potrebbe anche voler guardare nohup (es. 'Nohup python background_test.py') assumendo che si voglia che il demone continui a funzionare dopo essersi disconnessi) – Foon

+1

C'è un modo più semplice per farlo usando' python-daemon' che è il "libreria di processi demone standard": http://stackoverflow.com/a/8375012/462302 – aculich

5

Utilizzando & nel guscio è probabilmente il modo più semplice morti come descritto Greg.

Se si vuole veramente creare un demone potente, è necessario controllare il comando os.fork().

L'esempio da 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() 

E poi si potrebbe mettere qualsiasi compito avevi bisogno all'interno del blocco doTask().

Non è necessario avviarlo utilizzando & e consentirebbe di personalizzare ulteriormente l'esecuzione.

83

Invece di scrivere il proprio daemon, utilizzare invece python-daemon! python-daemon implementa la specifica daemon ben educata di PEP 3143, "Libreria di processi demone standard".

Ho incluso un codice di esempio basato sulla risposta accettata a questa domanda e anche se il codice sembra quasi identico, ha un'importante differenza fondamentale. Senza python-daemon si dovrebbe usare & per mettere il processo in background e nohup e per evitare che il processo venga ucciso quando si esce dalla shell. Invece questo si staccerà automaticamente dal tuo terminale quando eseguirai il programma.

Ad esempio:

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

Per eseguire in realtà è:

python background_test.py 

e notare l'assenza di & qui.

Inoltre, this other stackoverflow answer spiega in dettaglio i numerosi vantaggi dell'utilizzo di python-daemon.

+1

Sareste sorpresi, ma l'autore PEP e l'autore della biblioteca sono la stessa persona. Quindi sì, la libreria implementa molto bene quel PEP :) – Reishin

+0

Dici "questa altra risposta StackOverflow" ma link a una domanda, non a una risposta. La risposta selezionata alla domanda a cui si collega non utilizza (al momento di questo commento) python-daemon. Forse intendevi https://stackoverflow.com/a/688448/117471? –