Ejemplo de multiproceso Python no funciona

Estoy intentando aprender a usar el multiprocessing pero no consigo que funcione. Aquí está el código directamente de la documentación.

 from multiprocessing import Process def f(name): print 'hello', name if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() 

debería salir

‘Hola Bob’

pero en cambio me dan

>

no hay errores ni otros mensajes, simplemente se queda ahí, se ejecuta en IDLE desde un archivo .py guardado en una máquina con Windows 7 con la versión de 32 bits de Python 2.7

Mi conjetura es que está utilizando IDLE para intentar ejecutar este script. Desafortunadamente, este ejemplo no se ejecutará correctamente en IDLE. Tenga en cuenta el comentario al principio de los documentos :

Nota La funcionalidad dentro de este paquete requiere que el módulo principal sea ​​importable por los niños. Esto está cubierto en las pautas de progtwigción, sin embargo, vale la pena señalarlo aquí. Esto significa que algunos ejemplos, como el multiprocesamiento. Los ejemplos de las herramientas no funcionarán en el intérprete interactivo.

El módulo __main__ no es importable por los hijos en IDLE, incluso si ejecuta el script como un archivo con IDLE (lo que comúnmente se hace con F5).

Funciona.

He marcado los cambios necesarios para que su muestra se ejecute utilizando comentarios:

 from multiprocessing import Process def f(name): print 'hello', name #indent if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join()` # remove ` (grave accent) 

resultado:

 from multiprocessing import Process def f(name): print 'hello', name if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() 

Salida de mi computadora portátil después de guardarlo como ex1.py:

 reuts@reuts-K53SD:~/python_examples$ cat ex1.py #!/usr/bin/env python from multiprocessing import Process def f(name): print 'hello', name if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() reuts@reuts-K53SD:~/python_examples$ python ex1.py hello bob 

El problema no es IDLE. El problema es intentar imprimir en sys.stdout en un proceso que no tiene sys.stdout. Es por eso que Spyder tiene el mismo problema. Es probable que cualquier progtwig GUI en Windows tenga el mismo problema.

En Windows, al menos, los progtwigs GUI generalmente se ejecutan en un proceso sin stdin, stdout o stderr streams. Windows espera que los progtwigs GUI interactúen con los usuarios a través de widgets que pintan píxeles en la pantalla (la G en Gráficos) y reciben eventos clave y de mouse desde el sistema de eventos de Windows. Eso es lo que hace la GUI IDLE, usando el envoltorio tkinter del marco de la GUI tcl tk.

Cuando IDLE ejecuta el código de usuario en un subproceso, idlelib.run se ejecuta primero y reemplaza Ninguno para los flujos estándar con objetos que interactúan con IDLE a través de un socket. Luego se exec () s código de usuario. Cuando el código de usuario ejecuta el multiprocesamiento, el multiprocesamiento inicia procesos adicionales que no tienen flujos estándar, pero nunca los obtienen.

La solución es iniciar IDLE en una consola: python -m idlelib.idle (el .idle no es necesario en 3.x). Los procesos iniciados en una consola consiguen que las secuencias std se conecten a la consola. Lo mismo ocurre con otros subprocesos. El stdout real (en oposición a sys.stdout) de todos los procesos es la consola. Si uno ejecuta el tercer ejemplo en el documento,

 from multiprocessing import Process import os def info(title): print(title) print('module name:', __name__) print('parent process:', os.getppid()) print('process id:', os.getpid()) def f(name): info('function f') print('hello', name) if __name__ == '__main__': info('main line') p = Process(target=f, args=('bob',)) p.start() p.join() 

luego el bloque ‘línea principal’ va al shell IDLE y el bloque ‘función f’ va a la consola.

Este resultado muestra que la afirmación de Justin Barber de que el archivo de usuario ejecutado por IDLE no se puede importar en procesos iniciados mediante multiprocesamiento no es correcta.

EDITAR: Python guarda el stdout original de un proceso en sys.__stdout__ . Aquí está el resultado en el shell de IDLE cuando IDLE se inicia normalmente en Windows, como un proceso de GUI puro.

 >>> sys.__stdout__ >>> 

Aquí está el resultado cuando IDLE se inicia desde CommandPrompt.

 >>> import sys >>> sys.__stdout__ <_io.TextIOWrapper name='' mode='w' encoding='utf-8'> >>> sys.__stdout__.fileno() 1 

Los números de archivo estándar para stdin, stdout y stderr son 0, 1, 2. Ejecute un archivo con

 from multiprocessing import Process import sys def f(name): print('hello', name) print(sys.__stdout__) print(sys.__stdout__.fileno()) if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() 

en IDLE se inició en la consola y la salida es la misma.

Lo más probable es que su proceso principal salga antes de que se descargue el sysout. Prueba esto:

 from multiprocessing import Process import sys def f(name): print 'hello', name if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() p.join() # make sure all output has been processed before we exit sys.stdout.flush() 

Si esto no funciona, intente agregar time.sleep(1) como la última statement.

Tuve el problema de que el multiprocesamiento no funcionaba en Spyder y siempre aterrizaba aquí. Lo resolví utilizando subprocesos en lugar de multiprocesamiento. como se describe aquí: https://pymotw.com/2/threading/

 import threading def worker(num): """thread worker function""" print 'Worker: %s' % num return threads = [] for i in range(5): t = threading.Thread(target=worker, args=(i,)) threads.append(t) t.start()