Pregunta

Recientemente he necesaria para escribir un script que realiza una os.fork () a dividirse en dos procesos. El proceso hijo se convierte en un proceso de servidor y pasa los datos al proceso padre utilizando una tubería creada con os.pipe () . El niño cierra la 'r' extremo de la tubería y el padre cierra la 'w' extremo del tubo, como de costumbre. Cómo convierto los rendimientos de la tubería () en objetos de archivo con os.fdopen .

El problema que estoy teniendo es la siguiente: El proceso con éxito horquillas, y el niño se convierte en un servidor. Todo funciona muy bien y el niño diligentemente escribe datos en el read() extremo abierto del tubo. Por desgracia, al final de la tubería matriz hace dos cosas extrañas:
A) se bloquee en la operación <=> en el <=> extremo de la tubería.
En segundo lugar, no puede leer los datos que se puso en el tubo a menos que el <=> extremo está cerrado por completo.

inmediatamente pensé que buffering era el problema y ha añadido pipe.flush () llamadas, pero no sirvió de nada.

¿Alguien puede arrojar algo de luz sobre por qué los datos no aparece hasta el extremo de escritura está completamente cerrada? Y es que hay una estrategia para hacer que el <=> no bloqueo de llamadas?

Este es mi primer programa en Python que se bifurcan o tubos utilizados, por lo que me perdonen si he cometido un error simple.

¿Fue útil?

Solución

¿Está utilizando read () sin especificar un tamaño, o el tratamiento de la tubería como un iterador (for line in f)? Si es así, eso es probablemente el origen del problema - read () se define a leer hasta el final del archivo antes de regresar, en lugar de sólo leer lo que está disponible para su lectura. Eso significa que bloqueará hasta que el niño llama a close ().

En el código de ejemplo los vinculados a, esto está bien - el padre está actuando de una forma de bloqueo, y sólo usar el niño con fines de aislamiento. Si desea continuar, entonces o bien utilizar sin bloqueo IO como en el código que envió (pero estar preparado para hacer frente a los datos de media completa), o leer en trozos (por ejemplo r.read (tamaño) o r.readline () ) que bloqueará sólo hasta un tamaño / línea específica ha sido leído. (Usted todavía tiene que llamar al ras en el niño)

Parece que el tratamiento de la tubería como un iterador está usando alguna de tampón más así, por "for line in r:" no le puede dar lo que quiere si necesita cada línea para ser consumidos de inmediato. Puede ser posible desactivar esto, pero simplemente especificando 0 para el tamaño del buffer en fdopen no parece suficiente.

Aquí está un ejemplo de código que debería funcionar:

import os, sys, time

r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)

pid = os.fork()
if pid:          # Parent
    w.close()
    while 1:
        data=r.readline()
        if not data: break
        print "parent read: " + data.strip()
else:           # Child
    r.close()
    for i in range(10):
        print >>w, "line %s" % i
        w.flush()
        time.sleep(1)

Otros consejos

Uso

fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)

Antes de invocar la lectura () resuelto ambos problemas. La lectura () llamada ya no está bloqueando y los datos aparece después de sólo un color () en el extremo de escritura.

veo que haya resuelto el problema de bloqueo de E / S y almacenamiento temporal.

Una nota si decide intentar un enfoque diferente: el subproceso es el equivalente / un reemplazo para el idioma tenedor / exec. Parece que eso no es lo que está haciendo: usted tiene sólo un tenedor (no un ejecutivo) y el intercambio de datos entre los dos procesos - en este caso la multiprocessing módulo (en Python 2.6+) sería un mejor ajuste.

El "padre" frente a la parte "niño" de tenedor en una aplicación Python es tonta. Es un legado de días UNIX de 16 bits. Es una afectación de un día en el tenedor / exec y exec eran cosas importantes para aprovechar al máximo de un diminuto procesador.

Romper el código Python en dos partes separadas:. Padres e hijos

La pieza padre debe usar subproceso para ejecutar la parte del niño.

Un tenedor y exec pueden ocurrir en algún lugar allí - pero no es necesario para cuidar

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top