En mode UNIX typique, read(2)
renvoie 0 octet pour indiquer la fin du fichier, ce qui peut signifier :
- Il n'y a plus d'octets dans un fichier
- L'autre extrémité d'un socket a coupé la connexion
- L'écrivain a fermé un tuyau
Dans votre cas, fifo.read()
renvoie une chaîne vide, car le rédacteur a fermé son descripteur de fichier.
Vous devriez détecter ce cas et sortir de votre boucle :
lecteur.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))
Exemple de séance
Terminal 1 :
$ python reader.py
Opening FIFO...
<blocks>
Terminal 2 :
$ echo -n 'hello' > mypipe
Terminal 1 :
FIFO opened
Read: "hello"
Writer closed
$
Mise à jour 1 - Réouverture continue
Vous indiquez que vous souhaitez continuer à écouter les écritures sur le tube, probablement même après la fermeture d'un écrivain.
Pour le faire efficacement, vous pouvez (et devriez) profiter du fait que
Normalement, ouvrir les blocs FIFO jusqu'à ce que l'autre extrémité soit également ouverte.
Ici, j'ajoute une autre boucle autour de open
et le read
boucle. De cette façon, une fois le tube fermé, le code tentera de le rouvrir, ce qui bloquera jusqu'à ce qu'un autre écrivain ouvre le tube :
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>
... et ainsi de suite.
Vous pouvez en savoir plus en lisant le man
page pour les tuyaux :
- PIPE(7) - Manuel du programmeur Linux
- FIFO(7) - Manuel du programmeur Linux
(Des années plus tard) Si je comprends le cas d'utilisation de l'OP en utilisant for ... in ...
fait exactement ce que l'on souhaite :
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
for line in fifo:
print(line)
Ce programme attend patiemment l'entrée du fifo jusqu'à ce qu'elle soit fournie, puis l'imprime à l'écran. Aucun processeur n'est utilisé entre-temps.
C'est aussi la méthode la plus idiomatique en Python, je la recommande donc plutôt que d'utiliser directement read().
Si le côté client écrivant dans le fifo se ferme, la boucle for se termine et le programme se ferme. Si vous vouliez qu'il rouvre le fifo pour attendre que le prochain client l'ouvre vous pouvez mettre le for
section dans une boucle while :
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
Cela rouvrira le fifo et attendra comme d'habitude.