Python read named PIPE

In typical UNIX fashion, read(2) returns 0 bytes to indicate end-of-file which can mean:

  • There are no more bytes in a file
  • The other end of a socket has shutdown the connection
  • The writer has closed a pipe

In your case, fifo.read() is returning an empty string, because the writer has closed its file descriptor.

You should detect that case and break out of your 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))

Example session

Terminal 1:

$ python reader.py 
Opening FIFO...
<blocks>

Terminal 2:

$ echo -n 'hello' > mypipe 

Terminal 1:

FIFO opened
Read: "hello"
Writer closed
$ 

Update 1 – Continuously re-open

You indicate that you want to keep listening for writes on the pipe, presumably even after a writer has closed.

To do this efficiently, you can (and should) take advantage of the fact that

Normally, opening the FIFO blocks until the other end is opened also.

Here, I add another loop around open and the read loop. This way, once the pipe is closed, the code will attempt to re-open it, which will block until another writer opens the 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))

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>

… and so on.


You can learn more by reading the man page for pipes:

  • PIPE(7) – Linux Programmer’s Manual
  • FIFO(7) – Linux Programmer’s Manual

Leave a Comment