Al estilo típico de UNIX, read(2)
devuelve 0 bytes para indicar el final del archivo, lo que puede significar:
- No hay más bytes en un archivo
- El otro extremo de un enchufe ha cerrado la conexión
- El escritor ha cerrado una tubería
En tu caso, fifo.read()
está devolviendo una cadena vacía, porque el escritor ha cerrado su descriptor de archivo.
Deberías detectar ese caso y salir de tu ciclo:
lector.py :
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
Sesión de ejemplo
Terminal 1 :
$ python reader.py
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminal 1 :
FIFO opened
Read: "hello"
Writer closed
$
Actualización 1:reapertura continua
Indica que desea seguir escuchando las escrituras en la canalización, presumiblemente incluso después de que un escritor haya cerrado.
Para hacer esto de manera eficiente, puede (y debe) aprovechar el hecho de que
Normalmente, se abren los bloques FIFO hasta que se abre también el otro extremo.
Aquí, agrego otro bucle alrededor de open
y el read
círculo. De esta manera, una vez que se cierre la tubería, el código intentará volver a abrirla, lo que bloqueará hasta que otro escritor abra la tubería:
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
while True:
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
Terminal 1 :
$ python reader.py
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminal 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminal 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
... y así sucesivamente.
Puede obtener más información leyendo el man
página para tuberías:
- PIPE(7) - Manual del programador de Linux
- FIFO(7) - Manual del programador de Linux
(Años después) Si entiendo el caso de uso del OP usando for ... in ...
hace exactamente lo que se desea:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
for line in fifo:
print(line)
Este programa espera pacientemente la entrada del fifo hasta que se proporciona, luego lo imprime en la pantalla. Mientras tanto, no se utiliza ninguna CPU.
Esta es también la forma más idiomática en Python, por lo que la recomendaría en lugar de usar read() directamente.
Si el lado del cliente que escribe en el fifo se cierra, el bucle for finaliza y el programa se cierra. Si quisieras que volviera a abrir el fifo para esperar a que el próximo cliente lo abra puedes poner el for
sección en un ciclo while:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
Esto reabrirá el fifo y esperará como de costumbre.