Python: Actualizar la variable local en un proceso paralelo desde el progtwig principal

Soy relativamente nuevo en la progtwigción, y lo que pido puede ser una tarea que no es posible. Lo que quiero hacer es iniciar un proceso paralelo, que se ejecutará continuamente hasta que el usuario lo solicite. Una vez que el proceso ha comenzado, me gustaría actualizar una de las variables locales dentro del proceso paralelo desde el progtwig principal sin detener el proceso. Para un ejemplo muy simple, el proceso paralelo que me gustaría ejecutar sería el siguiente:

import time def loop(i): while 1: print i i+=1 time.sleep(1) 

Que continuamente itera y actualiza i . Para mayor claridad el progtwig para padres contendrá:

 from multiprocessing import Process from loop import loop i = 1 p = Process(target = loop, args = (i)) p.start() 

Desde el progtwig principal, una vez que se haya iniciado “bucle”, me gustaría poder cambiar la entrada “i” a otro número y hacer que el bucle continúe en iteración dado el siguiente valor inicial. Si alguien tiene alguna idea sobre cómo hacer esto, sería muy apreciado.

Puede usar una cola para pasar datos entre los procesos:

 from multiprocessing import Process, Queue from loop import loop i = 1 q = Queue() q.put(i) p = Process(target=loop, args=(q, )) p.start() 

Cuando quiera transmitir un nuevo valor de i al otro proceso, simplemente póngalo en la cola.

Cambie su módulo loop.py en consecuencia:

 def loop(q): while True: i = q.get() print i 

En su código principal, puede poner nuevos valores para el proceso:

 while True: i+=1 q.put(i) time.sleep(1) 

No hay nada malo con una cola aquí, pero probablemente sea más idiomático usar “memoria compartida” en su lugar. Menos gastos generales. Aquí hay un ejemplo de progtwig autocontenido:

 import time def loop(i): while 1: print i.value i.value += 1 time.sleep(1) if __name__ == "__main__": from multiprocessing import Process, Value i = Value("i", 1) # "i" for integer, initial value 1 p = Process(target=loop, args=(i,)) p.start() for base in range(100, 600, 100): time.sleep(2) i.value = base 

Eso probablemente mostrará 🙂

 1 2 100 101 200 201 300 301 400 401 500 501 502 503 504 505 506 ... 

Pero cuidado: a cambio de ser más rápido, esto también es más frágil. Los tipos de datos que puede compartir de esta manera se heredan básicamente del lenguaje C y generalmente no son tan ricos como los tipos de datos de Python. En el ejemplo anterior, el código de tipo "i" significa que estamos compartiendo un C int firmado, que generalmente es un entero con signo de 32 bits. Si, por ejemplo, i.value alcanza 2147483647, y le agregamos 1, de repente se convertirá en -2147483648 (sí, negativo!). Los ints de Python son ilimitados, pero los ints no lo son.

Use una cola . (Python 2 es Queue )

Hay algunas formas de consumir de la cola. La implementación ingenua (es decir, la que tiene una condición de carrera) es simplemente hacer if q.empty() . Esta es una mala práctica, pero no lo lastimaría, ya que no es de misión crítica si pierde un tic.

El mejor método es usar excepciones para el control de flujo:

 q = queue.Queue() try: q.get(False) #non-blocking get() #update value of i, etc except queue.Empty: #do stuff here as before