Mejor uso multihilo de subproceso Python. ¿Abrir y comunicar ()?

Estoy ejecutando varios comandos que pueden tardar algún tiempo, en paralelo, en una máquina Linux que ejecute Python 2.6.

Por lo tanto, utilicé la clase subprocess.Popen y el método process.communicate() para paralelizar la ejecución de varios grupos de comandos y capturar la salida inmediatamente después de la ejecución.

 def run_commands(commands, print_lock): # this part runs in parallel. outputs = [] for command in commands: proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) output, unused_err = proc.communicate() # buffers the output retcode = proc.poll() # ensures subprocess termination outputs.append(output) with print_lock: # print them at once (synchronized) for output in outputs: for line in output.splitlines(): print(line) 

En otro lugar se llama así:

 processes = [] print_lock = Lock() for ...: commands = ... # a group of commands is generated, which takes some time. processes.append(Thread(target=run_commands, args=(commands, print_lock))) processes[-1].start() for p in processes: p.join() print('done.') 

El resultado esperado es que cada salida de un grupo de comandos se muestra a la vez, mientras que su ejecución se realiza en paralelo.

Pero desde el segundo grupo de salida (por supuesto, el hilo que se convierte en el segundo se modifica debido a la indeterminación de la progtwigción), comienza a imprimir sin nuevas líneas y agrega espacios hasta el número de caracteres impresos en cada línea anterior y el eco de entrada se activa. apagado: el estado del terminal es “confuso” o “bloqueado”. (Si reset comando reset shell, restaura el normal).

    Al principio, traté de encontrar la razón del manejo de '\r' , pero no fue la razón. Como se ve en mi código, lo splitlines() correctamente usando splitlines() , y confirmé que con la función repr() aplicada a la salida.

    Creo que la razón es el uso concurrente de tuberías en Popen y se communicate() para stdout / stderr. Intenté el método abreviado check_output en Python 2.7, pero no tuve éxito. Por supuesto, el problema descrito anteriormente no se produce si serializo todas las ejecuciones de comandos y se imprime.

    ¿Hay alguna mejor manera de manejar Popen y communicate() en paralelo?

    Un resultado final inspirado en el comentario de JFSebastian.

    http://bitbucket.org/daybreaker/kaist-cs443/src/247f9ecf3cee/tools/manage.py

    Parece ser un error de Python.

    No estoy seguro de que esté claro qué es lo que en realidad debe estar haciendo run_commands, pero parece que simplemente está haciendo una encuesta en un subproceso, ignorando el código de retorno y continuando en el bucle. Cuando llega a la parte donde está imprimiendo la salida, ¿cómo podría saber que los subprocesos se han completado?

    En su código de ejemplo noté su uso de:

     for line in output.splitlines(): 

    para abordar parcialmente la cuestión de ” / r “; uso de

     for line in output.splitlines(True): 

    hubiera sido de ayuda