Toto
Toto

Reputation: 89

Behaviour of open() vs os.open() when using pipes

I have been struggling with writing and reading pipes. The problem was that on one side I was treating the pipe through an file-object obtained through open(). And on the other side I was using a file-descriptor obtained by "low-level" os.open(). Although looking similar the code behaves very different and I don't really understand why.

I've made a little example. I am varying the method to write to the pipe.In write_1.py I use os.open() and erverything is working as expected. In write_2.py using open() , when reading from the pipe I get an EAGAIN-error and get meaningful output only when the writing side has closed using pipe.close() in the end.

Reading in both cases in the same way, see read.py. Can you explain the different behaviour?

(Python version 3.5.2)

Files

# write_1.py
import os
import errno
import time

bufferSize = 100
PATH = "pipe"
i = 0

pipe = os.open(PATH, os.O_WRONLY | os.O_NONBLOCK)

while i < 20:
    i +=1
    my_str = "written {0}-times".format(i)
    try:
        input = os.write(pipe, my_str.encode())
    except OSError as err:
        if err.errno == 11:
            print("error 11")
            continue
        else:
            raise err
    if input:
        print("written {0} chars ".format(input))
    print("Sleep 500 ms")
    time.sleep(0.5)

os.close(pipe)
# write_2.py
import os
import errno
import time

bufferSize = 100
PATH = "pipe"
i = 0

pipe = open(PATH, "w")
fd = pipe.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

while i < 20:
    i +=1
    my_str = "written {0}-times".format(i)
    try:
        input = pipe.write(my_str)
    except OSError as err:
        if err.errno == 11:
            print("error 11")
            continue
        else:
            raise err
    if input:
        print("written {0} chars ".format(input))
    print("Sleep 500 ms")
    time.sleep(0.5)

pipe.close()

# read.py
import os
import errno
import time

bufferSize = 100
PATH = "pipe"
i = 0

pipe = os.open(PATH, os.O_RDONLY | os.O_NONBLOCK)

while i < 100:
    i +=1
    try:
        input = os.read(pipe, bufferSize)
    except OSError as err:
        if err.errno == 11:
            print("error 11")
            print("Sleep 500 ms")
            time.sleep(0.5)
            continue
        else:
            raise err
    if input:
        print(input)
    print("Sleep 500 ms")
    time.sleep(0.5)

os.close(pipe)

Upvotes: 1

Views: 1413

Answers (1)

user2357112
user2357112

Reputation: 280963

With open, you have accepted the default buffering setting (by not providing a buffering argument), so you're getting a buffered file object. This buffer is separate from any OS-level buffering.

With os.open, there is no file object and no file-object-level buffering.

(Also, you opened your pipe in blocking I/O mode with open, but that's not the cause of the difference you're seeing.)

Upvotes: 2

Related Questions