[Python-Dev] Draft PEP to make file objects support non-blocking mode.

Donovan Baarda abo at minkirri.apana.org.au
Mon Mar 21 10:39:50 CET 2005


From: "Peter Astrand" <astrand at lysator.liu.se>
> On Mon, 21 Mar 2005, Donovan Baarda wrote:
> This is no "trap". When select() indicates that you can write or read, it
> means that you can write or read at least one byte. The .read() and
> .write() file methods, however, always writes and reads *everything*.
> These works, basically, just like fread()/fwrite().

yep, which is why you can only use them reliably in a select loop if you
read/write one byte at a time.

> > The only ways to ensure that a select process does not block like this,
> > without using non-blocking mode, are;
> >
> > 1) use a buffer size of 1 in the select process.
> >
> > 2) understand the child process's read/write behaviour and adjust the
> > selector process accordingly... ie by making the buffer sizes just right
> > for the child process,
> 3) Use os.read / os.write.

but os.read / os.write will block too. Try it... replace the file
read/writes in selector.py. They will only do partial reads if the file is
put into non-blocking mode.

> > I think the fread/fwrite and read/write behaviour is posix standard and
> > possibly C standard stuff... so it _should_ be the same on other
> > platforms.
> Sorry if I've misunderstood your point, but fread()/fwrite() does not
> return EAGAIN.

no, fread()/fwrite() will return 0 if nothing was read/written, and ferror()
will return EAGAIN to indicated that it was a "would block" condition.... at
least I think it does... the man page simply says ferror() returns a
non-zero value.

Looking at the python implementation of file.read(), for an empty fread()
where ferror() is non zero, it only raises IOError if errno is not EAGAIN or
EWOULDBLOCK. It blindly clearerr()'s for any other partial read.

The implementation of file.write() raises IOError whenever there is an
incomplete write.

So it looks, as I pointed out in the draft PEP, that the current file.read()
supports non-blocking mode, but file.write() doesn't... a bit asymmetric :-)

Donovan Baarda                http://minkirri.apana.org.au/~abo/

More information about the Python-Dev mailing list