Subproceso de Python que pierde el 10% de la salida estándar de un programa

Tengo un programa que debe llamarse como un subproceso con python. El programa ha sido escrito en java. si lo se...

de todos modos, necesito capturar toda la salida de dicho programa.

Desafortunadamente, cuando llamo a subprocess.popen2 o subprocess.Popen con communica[0], pierdo alrededor del 10 % de los datos de salida cuando uso un subprocess.PIPE asignado a stdout Y cuando uso un descriptor de archivo (el retorno de una apertura) asignado a stdout.

La documentación en el subproceso es bastante explícita en cuanto a que el uso de subproceso. PIPE es volátil si está tratando de capturar toda la salida de un proceso secundario.

Actualmente estoy usando pexpect para volcar la salida en un archivo tmp, pero eso lleva una eternidad por razones obvias.

Me gustaría mantener todos los datos en la memoria para evitar escrituras en el disco.

cualquier recomendación es bienvenida! ¡Gracias!

import subprocess

cmd = 'java -Xmx2048m -cp "/home/usr/javalibs/class:/home/usr/javalibs/libs/dependency.jar" --data data --input input" 

# doesn't get all the data
#
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

OR
# doesn't get all the data
#
fd = open("outputfile",'w')
p = subprocess.Popen(cmd, stdout=fd, shell=True)
p.communicate()
fd.close() # tried to use fd.flush() too.

# also tried
# p.wait() instead of p.communicate(), but wait doesn't really wait for the java program to finish running - it doesn't block

OR
# also fails to get all the data
#
import popen2
(rstdout, rstdin) = popen2.popen2(cmd)

El resultado esperado es una serie de líneas ascii (un par de miles). las líneas contienen un número y un carácter de fin de línea

0\n
1\n
4\n
0\n
...

preguntado el 21 de mayo de 12 a las 18:05

¿Es posible que parte de la salida se escriba en stderr? -

¿Podemos tener algo de código de Python? -

¿Qué "10%" te estás perdiendo? ¿Es al principio, al final? ¿Qué salida esperabas? -

¿Estás seguro de que tu subproceso Java no se está bifurcando? Eso podría explicar por qué su wait() parece que la llamada no se bloquea. -

Para ser más específicos, usando subprocess.PIPE o asignar un fd a la salida del subproceso es esencialmente lo mismo que hace su shell cuando realiza una redirección de salida a un archivo (el sistema operativo dup2() llamada al sistema). Puede asumir con seguridad que esa parte está funcionando. Puede intentar agregar "` | tee outputcopy" at the end of your command there; then you could check that outputcopy` tiene todas las líneas que esperas. Si no es así, tal vez su programa Java no esté funcionando del todo bien. -

2 Respuestas

Había usado subprocess con una salida mucho mayor en stdout pero no he visto tal problema. Es difícil concluir cuál es la causa raíz de lo que has mostrado. Verificaría lo siguiente:

Como p.wait() no te funciono Podría darse el caso de que al leer tu PIPE su programa Java todavía está ocupado imprimiendo el último 10%. Obtener p.wait() recto primero:

  • Inserte una espera lo suficientemente grande (digamos 30 segundos) antes de leer el PIPE, aparece tu 10%?
  • es dudoso que p.wait() no se bloquea en su programa Java. ¿Su programa java procesa aún más otro programa?
  • comprobar el valor de retorno de p.wait(). ¿Su programa java terminó normalmente?

Si el problema no radica en su modelo de concurrencia, verifique si está imprimiendo correctamente en su programa Java:

  • Qué función usó en su programa Java para imprimir en stdout? ¿Es propenso a o ignorando IOException?
  • ¿Descargaste la corriente correctamente? El último 10% podría estar en su búfer sin un lavado adecuado cuando finalice su programa java.

contestado el 21 de mayo de 12 a las 19:05

Me pondré en contacto con usted de inmediato: trabajaré en las notas de jdi en un momento. ¡Gracias! - Connecticut_

Debe ser algo relacionado con el proceso que realmente está llamando. Puede verificar esto haciendo una prueba simple con otro script de python que repite las líneas:

fuera.py

import sys

for i in xrange(5000):
    print "%d\n" % i

sys.exit(0)

prueba.py

import subprocess

cmd = "python out.py"
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

print output

Por lo tanto, puede verificar que el problema no es el tamaño de los datos, sino la comunicación con el proceso al que está llamando.

También debe confirmar la versión de python que está ejecutando, ya que he leído sobre problemas anteriores relacionados con el búfer interno de Popen (pero el uso de un identificador de archivo separado, como usted sugirió, normalmente me lo solucionó).

Sería un problema de búfer si la llamada del subproceso se colgara indefinidamente. Pero si el proceso se está completando, solo faltan líneas, entonces Popen está haciendo su trabajo.

contestado el 21 de mayo de 12 a las 20:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.