2010-03-04 26 views
9

documentación de Python a Popen estados:¿Alguien puede explicar el punto muerto del buffer de tubería?

Advertencia Utilice comunicarse() en lugar de .stdin.write, .stdout.read o .stderr.read para evitar puntos muertos debido a cualquiera de los otros tampones de tubería OS llenar y bloqueando el proceso del niño.

Ahora, estoy tratando de descubrir cómo puede ocurrir este punto muerto y por qué.

Mi modelo mental: el subproceso produce algo en stdout/err, que se almacena en el búfer y después de llenar el búfer, se enjuaga a stdout/err de subproceso, que se envía a través del canal al proceso principal.

Según lo que dice la documentación, la tubería tiene su propio búfer y cuando se llena o termina el subproceso, se vacía al proceso principal.

De cualquier manera (con buffer de tubería o no), no estoy del todo seguro de cómo puede ocurrir un punto muerto. Lo único que se me ocurre es algún tipo de proceso de búfer de tuberías del sistema operativo "global" que buscará, lo cual suena extraño. Otra es que más procesos compartirán el mismo conducto, lo que no debería suceder por sí mismo.

¿Alguien puede explicar esto?

Respuesta

6

Cuidado, esto tiene un error sutil.

Mi modelo mental: subproccess produce algo a la salida estándar/err, que es tamponada y después de búfer está lleno, es enrojecida por la salida estándar/err de subproccess, que se envía a través tubería de proceso padre.

El almacenamiento intermedio se comparte entre el proceso principal y secundario.

El subproceso produce algo en stdout, que es el mismo búfer del que se supone que debe leer el proceso principal.

Cuando se llena el búfer, la escritura se detiene hasta que se vacía el búfer. El color no significa nada para un tubo, ya que dos procesos comparten el mismo buffer.

La descarga a disco significa que el controlador del dispositivo debe presionar los bytes hacia abajo al dispositivo. Enjuagar un socket significa decirle a TCP/IP que deje de esperar para acumular un búfer y enviar cosas. Vaciarse en una consola significa dejar de esperar una nueva línea e introducir los bytes a través del controlador del dispositivo en el dispositivo.

+0

Esto es de lo que no estaba tan seguro. Gracias. – Almad

1

Puede producirse un interbloqueo cuando ambos almacenamientos intermedios (stdin y stdout) están llenos: su programa está esperando escribir más entradas al programa externo, y el programa externo está esperando leer primero de su búfer de salida.

Esto se puede resolver utilizando E/S sin bloqueo y priorizando correctamente los búferes. Puede intentar hacerlo funcionar usted mismo, pero communicate() simplemente lo hace por usted.

+0

Sí, pero estamos hablando de leer datos de mayor tamaño que la memoria. Pero gracias por la aclaración. – Almad

Cuestiones relacionadas