GNU/Linux >> Tutoriels Linux >  >> Linux

Python lit nommé PIPE

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.


Linux
  1. Commande Preug - SyntaxError:Parenthèses manquantes dans l'appel à 'print' - Solution

  2. ModuleNotFoundError :Aucun module nommé "IPython" [Réparer]

  3. Lecture continue à partir d'un tube nommé (chat ou queue -f) ?

  4. De quoi ai-je besoin pour lire les bases de données Microsoft Access à l'aide de Python ?

  5. Exemple d'utilisation de canaux nommés dans Linux Bash

Une introduction aux canaux et aux canaux nommés sous Linux

Instruction Python if..else

Tuyau B à D ? – A &&B || C | RÉ?

Erreur d'importation aucun module nommé zlib (brew python installé)

Comment lire le volume audio du microphone en temps réel en python et ffmpeg ou similaire

Pourquoi ai-je l'air de perdre des données en utilisant cette construction bash pipe ?