select.select and socket.setblocking

Steve Holden steve at holdenweb.com
Tue Dec 30 08:57:07 EST 2008


Laszlo Nagy wrote:
> I'm using this method to read from a socket:
> 
>    def read_data(self,size):
>        """Read data from connection until a given size."""
>        res = ""
>        fd = self.socket.fileno()
>        while not self.stop_requested.isSet():
>            remaining = size - len(res)
>            if remaining<=0:
>                break
>            # Give one second for an incoming connection so we can stop the
>            # server in seconds when needed
>            ready = select.select([fd], [], [], 1)
>            if fd in ready[0]:
>                data = self.socket.recv(min(remaining,8192)) # 8192 is
> recommended by socket.socket manual.
>                if not data:
>                    # select returns the fd but there is no data to read
> -> connection closed!
>                    raise TransportError("Connection closed.")
>                else:
>                    res += data
>            else:
>                pass
>        if self.stop_requested.isSet():
>            raise SystemExit(0)
>        return res
> 
> 
> This works: if I close the socket on the other side, then I see this in
> the traceback:
> 
>  File "/usr/home/gandalf/Python/Projects/OrbToy/orb/endpoint.py", line
> 233, in read_data
>    raise TransportError("Connection closed.")
> TransportError: Connection closed.
> 
> Also when I call stop_requested.set() then the thread stops within one
> seconds.
> 
> Then I switch to non blocking mode, my code works exactly the same way,
> or at least I see no difference.
> 
> I have read the socket programming howto (
> http://docs.python.org/howto/sockets.html#sockets ) but it does not
> explain how a blocking socket + select is different from a non blocking
> socket + select. Is there any difference?
> 
Well, ignoring your question for the moment, what's wrong with the
following (untested) code?

    def read_data(self, size):
        data = ""
        while len(data) < size:
            d = self.socket.read(size-len(data))
            if not d:
                raise TransportError("Socket closed while reading data")
            data += d
        return data

I feel the raw socket operations are easier to understand and less
confusing.

Since you don't want to return until you've read the data there really
doesn't seem to be any point using select(), which is mainly useful in
asynchronous operations (in which case you would have to use
non-blocking sockets). It's not obvious from your code how
self.stop_requested is supposed to change the result of its is_set()
method. Maybe that's where the select() comes in?

regards
 Steve
-- 
Steve Holden        +1 571 484 6266   +1 800 494 3119
Holden Web LLC              http://www.holdenweb.com/




More information about the Python-list mailing list