2012-01-16 6 views
5

Estoy tratando de ejecutar tres funciones (cada una puede tomar hasta 1 segundo para ejecutar) cada segundo. Luego me gustaría almacenar el resultado de cada función y escribirlas en archivos separados.Ejecutar múltiples funciones cada segundo, escribir el resultado en el archivo

Por el momento estoy usando Timer s para mi manejo de retraso. (Podría subclase Thread, pero eso es conseguir un poco complicado para este sencillo script)

def main: 
    for i in range(3): 
     set_up_function(i) 
     t = Timer(1, run_function, [i]) 
     t.start() 
    time.sleep(100) # Without this, main thread exits 

def run_function(i): 
    t = Timer(1, run_function, [i]) 
    t.start() 
    print function_with_delay(i) 

¿Cuál es la mejor manera de manejar la salida de function_with_delay? ¿Agregar el resultado a una lista global para cada función?

Entonces podría poner algo como esto al final de mi función principal:

... 
while True: 
    time.sleep(30) # or in a try/except with a loop of 1 second sleeps so I can interrupt 
    for i in range(3): 
     save_to_disk(data[i]) 

Pensamientos?


Editar: Añadido mi propia respuesta como una posibilidad

Respuesta

7

Creo que el módulo python Queue está diseñado precisamente para este tipo de situaciones. Se podría hacer algo como esto, por ejemplo:

def main(): 
    q = Queue.Queue() 
    for i in range(3): 
     t = threading.Timer(1, run_function, [q, i]) 
     t.start() 

    while True: 
     item = q.get() 
     save_to_disk(item) 
     q.task_done() 

def run_function(q, i): 
    t = threading.Timer(1, run_function, [q, i]) 
    t.start() 
    q.put(function_with_delay(i)) 
+1

+1 Esto funciona porque la salida es para separar archivos. Si no era trivial e involucraba una combinación de resultados, entonces tendría que esperar a que todos los artículos en cola terminen antes de escribir. Asegúrate de llamar 'task_done' en los elementos que obtienes también. – darvids0n

+0

¡Gran idea! Queue es seguro para subprocesos y es mucho mejor que list.append (data) –

+0

Agregué la llamada a 'task_done' como lo sugirió darvids0n. Gracias. – srgerg

1

yo diría almacenar una lista de listas (bool, str), donde bool es si la función ha terminado de ejecutarse y str es la salida. Cada función bloquea la lista con un mutex para anexar la salida (o si no le importa la seguridad del hilo, omita esto). Luego, tenga un simple bucle de sondeo que compruebe si todos los valores de bool son , y si es así, realice sus llamadas a save_to_disk.

0

Otra alternativa sería implementar una clase (tomado de this answer) que utiliza threading.Lock(). Esto tiene la ventaja de poder esperar en el ItemStore, y save_to_disk puede usar getAll, en lugar de sondear la cola. (¿Más eficiente para grandes conjuntos de datos?)

Esto es particularmente adecuado para escribir en un intervalo de tiempo establecido (es decir, cada 30 segundos), en lugar de una vez por segundo.

class ItemStore(object): 
    def __init__(self): 
     self.lock = threading.Lock() 
     self.items = [] 

    def add(self, item): 
     with self.lock: 
      self.items.append(item) 

    def getAll(self): 
     with self.lock: 
      items, self.items = self.items, [] 
     return items 
Cuestiones relacionadas