2011-11-05 5 views
8

En el siguiente programa, cuando anexo el proceso a una lista (algo aparentemente inútil que hacer), se ejecuta como se esperaba. Pero si elimino el apéndice, se llama al destructor de procesos muchas veces incluso antes de que se ejecute. Solo hay n construcciones pero (n)(n+1)/2 (donde n es el número de procesos) destrucciones. Esto me lleva a creer que cada proceso se copia en cada nuevo proceso y luego se destruye inmediatamente. Quizás así es como funciona el módulo de multiprocesamiento. Tiene sentido, ya que cada proceso es una bifurcación del actual. Pero, ¿cuál es el significado de agregar a la lista? ¿Por qué simplemente hacer eso detiene este comportamiento?Agregar un proceso a una lista (pero no hacer nada con él) altera el comportamiento del programa

Así es la prueba y la muestra de salida:

import multiprocessing 

class _ProcSTOP: 
    pass 

class Proc(multiprocessing.Process): 

    def __init__(self, q, s): 
     s.i += 1 
     self._i = s.i 
     self._q = q 
     print('constructing:', s.i) 
     super().__init__() 

    def run(self): 
     dat = self._q.get() 

     while not dat is _ProcSTOP: 
      self._q.task_done() 
      dat = self._q.get() 

     self._q.task_done() 
     print('returning: ', self._i) 

    def __del__(self): 
     print('destroying: ', self._i) 



if __name__ == '__main__': 

    q = multiprocessing.JoinableQueue() 
    s = multiprocessing.Manager().Namespace() 
    s.i = 0 
    pool = [] 

    for i in range(4): 
     p = Proc(q, s) 
     p.start() 
     pool.append(p) # This is the line to comment 

    for i in range(10000): 
     q.put(i) 

    q.join() 

    for i in range(4): 
     q.put(_ProcSTOP) 

    q.join() 

    print('== complete') 

Salida de ejemplo con append:

constructing: 1 
constructing: 2 
constructing: 3 
constructing: 4 
returning: 3 
returning: 2 
== complete 
returning: 1 
returning: 4 
destroying: 4 
destroying: 3 
destroying: 2 
destroying: 1 

Ejemplo de salida sin append:

constructing: 1 
constructing: 2 
constructing: 3 
destroying: 1 
constructing: 4 
destroying: 1 
destroying: 2 
destroying: 3 
destroying: 1 
destroying: 2 
returning: 1 
returning: 4 
returning: 2 
== complete 
returning: 3 
destroying: 1 
destroying: 3 
destroying: 2 
destroying: 4 
+0

¿usted ¿Y si tiene algo que ver con la recolección de basura? Los síntomas indican que es necesario mantener una referencia a la instancia de la clase. – Dave

+0

@Dave. Ese es un buen punto. Sospecho que estás en el camino correcto allí. – tjm

Respuesta

1

Agregar el objeto a una lista evitará que se elimine en procesos secundarios porque después de bifurcar llamará a "os._exit()" en lugar de borrar toda la pila

El código correspondiente está en multiprocesamiento/forking.py (constructor de Popen, que se llama el "p.start()")

self.pid = os.fork() 
if self.pid == 0: 
    if 'random' in sys.modules: 
     import random 
     random.seed() 
    code = process_obj._bootstrap() 
    sys.stdout.flush() 
    sys.stderr.flush() 
    os._exit(code) 

Dónde _bootstrap configuraciones del nuevo proceso y llama a "correr" (es el código de multiprocesamiento/process.py)

Cuestiones relacionadas