Let's say I want to read a line from a socket, using the standard socket
module:
def read_line(s):
ret = ''
while True:
c = s.recv(1)
if c == '\n' or c == '':
break
else:
ret += c
return ret
What exactly happens in s.recv(1)
? Will it issue a system call each time? I guess I should add some buffering, anyway:
For best match with hardware and network realities, the value of bufsize should be a relatively small power of 2, for example, 4096.
http://docs.python.org/library/socket.html#socket.socket.recv
But it doesn't seem easy to write efficient and thread-safe buffering. What if I use file.readline()
?
# does this work well, is it efficiently buffered?
s.makefile().readline()
The recv()
call is handled directly by calling the C library function.
It will block waiting for the socket to have data. In reality it will just let the recv()
system call block.
file.readline()
is an efficient buffered implementation. It is not threadsafe, because it presumes it's the only one reading the file. (For example by buffering upcoming input.)
If you are using the file object, every time read()
is called with a positive argument, the underlying code will recv()
only the amount of data requested, unless it's already buffered.
It would be buffered if:
you had called readline(), which reads a full buffer
the end of the line was before the end of the buffer
Thus leaving data in the buffer. Otherwise the buffer is generally not overfilled.
The goal of the question is not clear. if you need to see if data is available before reading, you can select()
or set the socket to nonblocking mode with s.setblocking(False)
. Then, reads will return empty, rather than blocking, if there is no waiting data.
Are you reading one file or socket with multiple threads? I would put a single worker on reading the socket and feeding received items into a queue for handling by other threads.
Suggest consulting Python Socket Module source and C Source that makes the system calls.