In tipico stile UNIX, read(2)
restituisce 0 byte per indicare la fine del file che può significare:
- Non ci sono più byte in un file
- L'altra estremità di un socket ha interrotto la connessione
- Lo scrittore ha chiuso una pipa
Nel tuo caso, fifo.read()
sta restituendo una stringa vuota, perché il writer ha chiuso il suo descrittore di file.
Dovresti rilevare quel caso e uscire dal tuo loop:
reader.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))
Sessione di esempio
Terminale 1 :
$ python reader.py
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminale 1 :
FIFO opened
Read: "hello"
Writer closed
$
Aggiornamento 1 - Riapertura continua
Indichi che vuoi continuare ad ascoltare le scritture sulla pipa, presumibilmente anche dopo che uno scrittore ha chiuso.
Per farlo in modo efficiente, puoi (e dovresti) sfruttare il fatto che
Normalmente, l'apertura dei blocchi FIFO fino a quando non viene aperta anche l'altra estremità.
Qui, aggiungo un altro giro attorno a open
e il read
ciclo continuo. In questo modo, una volta chiusa la pipe, il codice tenterà di riaprirla, il che si bloccherà finché un altro writer non aprirà la pipe:
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))
Terminale 1 :
$ python reader.py
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminale 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminale 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
... e così via.
Puoi saperne di più leggendo il man
pagina per pipe:
- PIPE(7) - Manuale del programmatore Linux
- FIFO(7) - Manuale del programmatore Linux
(Anni dopo) Se capisco il caso d'uso dell'OP usando for ... in ...
fa esattamente ciò che si desidera:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
for line in fifo:
print(line)
Questo programma attende pazientemente l'input dal fifo finché non viene fornito, quindi lo stampa sullo schermo. Nessuna CPU viene utilizzata nel frattempo.
Questo è anche il modo più idiomatico in Python, quindi lo consiglierei piuttosto che usare read() direttamente.
Se la scrittura lato client sul fifo si chiude, il ciclo for termina e il programma si chiude. Se vuoi che riapra il fifo per aspettare che il prossimo client lo apra puoi mettere il for
section in un ciclo while:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
Questo riaprirà il fifo e aspetterà come al solito.