2012-05-07 27 views
8

Tengo un script de Python simple que usa dos scripts de Python mucho más complicados, y hace algo con los resultados.Programación concurrente muy simple en Python

que tienen dos módulos, Foo y Bar, y mi código es el siguiente:

import Foo 
import Bar 

output = [] 

a = Foo.get_something() 
b = Bar.get_something_else() 

output.append(a) 
output.append(b) 

Ambos métodos toman mucho tiempo para funcionar, y tampoco depende de la otra, por lo que la solución obvia es ejecútelos en paralelo. Cómo puedo lograr esto, pero asegúrese de que se mantenga el orden: Cualquiera que termine primero debe esperar a que el otro finalice antes de que el script pueda continuar.

Avíseme si no me he aclarado lo suficiente, he intentado hacer que el código de ejemplo sea lo más simple posible.

EDIT:

Gracias ámbar, su solución funciona con un cambio ligero.

En lugar de llamar a start() de cada hilo cuando se crea, les estableció de esta manera:

threadname = threading.Thread(target=foo) 
threadname.start() 

Sin este que estaba recibiendo el error AttributeError: 'NoneType' object has no attribute 'join' y algunos muy comportamiento extraño con la concurrencia . Si edita su respuesta a continuación, la marcaré como resuelta.

Respuesta

20

En general, usaría threading para hacer esto.

En primer lugar, crear un hilo para cada cosa que desea ejecutar en paralelo:

import threading 

import Foo 
import Bar 

results = {} 

def get_a(): 
    results['a'] = Foo.get_something() 
a_thread = threading.Thread(target=get_a) 
a_thread.start() 

def get_b(): 
    results['b'] = Bar.get_something_else() 
b_thread = threading.Thread(target=get_b) 
b_thread.start() 

Entonces exigir tanto de ellos de haber terminado, utilice .join() tanto:

a_thread.join() 
b_thread.join() 

a la cual señale que sus resultados estarán en results['a'] y results['b'], por lo tanto, si desea obtener una lista ordenada:

output = [results['a'], results['b']] 

Nota: si ambas tareas son inherentemente intensivo de la CPU, puede que desee considerar multiprocessing lugar - debido a GIL de Python, un proceso de Python dada sólo utilizará siempre un núcleo de CPU, mientras que multiprocessing puede distribuir las tareas para separar los núcleos . Sin embargo, tiene una sobrecarga ligeramente mayor que threading, y por lo tanto si las tareas consumen menos CPU, puede que no sea tan eficiente.

+3

Enhebrar es útil para el código con ralentí. Si tiene muchos cálculos pesados, debe aconsejar el multiprocesamiento, ya que el enhebrado solo agregará retardos en este caso. – akaRem

+0

@akaRem Claro, puedo editar en una nota al respecto. – Amber

+0

Sí, requiere mucha CPU. Sin embargo, haré que esto funcione primero; Eché un vistazo rápido y las API son idénticas. – Rory

7
import multiprocessing 

import Foo 
import Bar 

results = {} 

def get_a(): 
    results['a'] = Foo.get_something() 



def get_b(): 
    results['b'] = Bar.get_something_else() 

process_a = multiprocessing.Process(target=get_a) 
process_b = multiprocessing.Process(target=get_b) 


process_b.start() 
process_a.start() 


process_a.join 
process_b.join 

Aquí está la versión de proceso de su programa.

NOTA: que en el subproceso hay estructuras de datos compartidas, por lo que debe preocuparse por el bloqueo, lo que evita manipulaciones erróneas y el ámbar mencionado anteriormente también tiene un problema GIL (bloqueo de intérprete global) y sus dos tareas son CPU intensivo, entonces esto significa que llevará más tiempo debido a las llamadas que notifican los hilos de adquisición y liberación del hilo. Sin embargo, si sus tareas eran intensivas en E/S, entonces no tendría mucho efecto.

Ahora, dado que no hay estructuras de datos compartidas en un proceso, no hay necesidad de preocuparse por LOCKS y porque funciona independientemente de GIL, por lo que realmente disfruta de la potencia real de los multiprocesadores.

nota simple para recordar: el proceso es el mismo que el hilo simplemente sin usar una estructuras de datos compartidos (todo funciona de manera aislada y se centra en la mensajería.)

la salida dabeaz.com le dio una buena presentación de la programación concurrente vez.