Reputation: 89
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)
# 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
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