Quiero ejecutar muchos procesos en paralelo con la capacidad de tomar stdout en cualquier momento. ¿Cómo debería hacerlo? ¿Debo ejecutar hilo para cada llamada subprocess.Popen()
, un qué?Subproceso de Python en paralelo
Respuesta
Puede hacerlo en un solo hilo.
Suponga que tiene una secuencia de comandos que imprime líneas en momentos aleatorios:
#!/usr/bin/env python
#file: child.py
import os
import random
import sys
import time
for i in range(10):
print("%2d %s %s" % (int(sys.argv[1]), os.getpid(), i))
sys.stdout.flush()
time.sleep(random.random())
y que le gustaría recoger la salida tan pronto como esté disponible, se puede utilizar en sistemas POSIX select
como @zigg suggested:
#!/usr/bin/env python
from __future__ import print_function
from select import select
from subprocess import Popen, PIPE
# start several subprocesses
processes = [Popen(['./child.py', str(i)], stdout=PIPE,
bufsize=1, close_fds=True,
universal_newlines=True)
for i in range(5)]
# read output
timeout = 0.1 # seconds
while processes:
# remove finished processes from the list (O(N**2))
for p in processes[:]:
if p.poll() is not None: # process ended
print(p.stdout.read(), end='') # read the rest
p.stdout.close()
processes.remove(p)
# wait until there is something to read
rlist = select([p.stdout for p in processes], [],[], timeout)[0]
# read a line from each process that has output ready
for f in rlist:
print(f.readline(), end='') #NOTE: it can block
Una solución más portátil (que debería funcionar en Windows, Linux, OS X) pueden utilizar hilos lector para cada proceso, consulte Non-blocking read on a subprocess.PIPE in python.
Aquí es os.pipe()
solución basada en que funciona en Unix y Windows:
#!/usr/bin/env python
from __future__ import print_function
import io
import os
import sys
from subprocess import Popen
ON_POSIX = 'posix' in sys.builtin_module_names
# create a pipe to get data
input_fd, output_fd = os.pipe()
# start several subprocesses
processes = [Popen([sys.executable, 'child.py', str(i)], stdout=output_fd,
close_fds=ON_POSIX) # close input_fd in children
for i in range(5)]
os.close(output_fd) # close unused end of the pipe
# read output line by line as soon as it is available
with io.open(input_fd, 'r', buffering=1) as file:
for line in file:
print(line, end='')
#
for p in processes:
p.wait()
Parece que multiplexa los stdout de todos los niños a un solo fd (output_fd) en su última solución. ¿Qué pasa si 2 niños imprimen al mismo tiempo? ¿Eso no estropeará la salida (por ejemplo, 'AAA \ n' + 'BBB \ n' -> 'ABBB \ nAA \ n') – dan3
@ dan3: es una preocupación válida . 'write's que son menores que los bytes' PIPE_BUF' son atómicos. De lo contrario, los datos de procesos múltiples pueden intercalarse. POSIX requiere al menos 512 bytes. En Linux, 'PIPE_BUF' es 4096 bytes. – jfs
Aquí hay una pregunta similar que publiqué recientemente aquí, http://stackoverflow.com/questions/36624056/running-a-secondary-script-in-a-new-terminal sería fantástico si pudiera ayudar, gracias en cualquier caso . –
No necesita ejecutar un hilo para cada proceso. Puede echar un vistazo a las transmisiones stdout
para cada proceso sin bloquearlas, y solo leer de ellas si tienen datos disponibles para leer.
Usted haga tenga cuidado de no bloquearlos accidentalmente, sin embargo, si no tiene intención de hacerlo.
Hago 'p = subprocess.Popen (...)' y luego 'print p.communicate() [0] 'varias veces. Pero 'communicate()' solo espera antes de que finalice el proceso. – sashab
Sí, por lo que no puede usar 'communicate()' si desea usar un único hilo. Hay otras formas de obtener stdout además de 'communicate()'. – Amber
Probablemente necesites consultar el módulo [seleccionar] (http://docs.python.org/library/select.html) para esperar en muchos subprocesos a la vez. – zigg
También puede obtener la salida estándar a partir de múltiples subprocesos simultáneamente usando twisted
:
#!/usr/bin/env python
import sys
from twisted.internet import protocol, reactor
class ProcessProtocol(protocol.ProcessProtocol):
def outReceived(self, data):
print data, # received chunk of stdout from child
def processEnded(self, status):
global nprocesses
nprocesses -= 1
if nprocesses == 0: # all processes ended
reactor.stop()
# start subprocesses
nprocesses = 5
for _ in xrange(nprocesses):
reactor.spawnProcess(ProcessProtocol(), sys.executable,
args=[sys.executable, 'child.py'],
usePTY=True) # can change how child buffers stdout
reactor.run()
- 1. Procesamiento paralelo en python
- 2. Valor compartido en python paralelo
- 3. argumentos de Python subproceso
- 4. Subproceso de python persistente
- 5. Subproceso FFMPEG y Python
- 6. Python subproceso Ayuda
- 7. Python: ¿Cómo puedo ejecutar las funciones de Python en paralelo?
- 8. Python subproceso de Bash: llaves
- 9. Supresión de salida en Python llamada subproceso
- 10. Interbloqueo en el subproceso de Python popen
- 11. Bibliotecas de procesamiento paralelo de Python
- 12. subproceso python que utiliza el subproceso de importación
- 13. Usar el módulo de subproceso Python 2.6 en Python 2.5
- 14. python getoutput() equivalente en el subproceso
- 15. Salida del subproceso Python en Windows?
- 16. En Python 2.5, ¿cómo elimino un subproceso?
- 17. Cómo utilizar subproceso popen Python
- 18. ScheduledExecutorService múltiples hilos en paralelo
- 19. líneas de lectura de subproceso de Python()?
- 20. Código de salida de subproceso de Python
- 21. Python, ejecuta herramientas de línea de comandos en paralelo
- 22. Devuelve el valor del subproceso de Python
- 23. Enviando SIGINT a un subproceso de python
- 24. El subproceso de Python parece ejecutar subprocesos
- 25. Uso del comodín del subproceso de Python
- 26. Qué es un subproceso de python
- 27. Python con matplotlib - dibujo de varias figuras en paralelo
- 28. sustitución del subproceso de popen2 con Python
- 29. Salida de subproceso Python a stdout
- 30. Perfil Python Uso de CPU por subproceso
posible duplicado de [cómo ejecutar varios ejecutables usando python?] (Http://stackoverflow.com/questions/9724499/how-to-run-several-executable-using-python) –
relacionado: Aquí es cómo [ ejecutar varios comandos de shell (y opcionalmente capturar su salida) concurrentemente] (http://stackoverflow.com/a/23616229/4279) – jfs