Receive data from socket stream

Jean-Paul Calderone exarkun at divmod.com
Mon Apr 28 09:58:50 EDT 2008


On Mon, 28 Apr 2008 08:30:03 -0500, Nick Craig-Wood <nick at craig-wood.com> wrote:
>Hrvoje Niksic <hniksic at xemacs.org> wrote:
>>  Nick Craig-Wood <nick at craig-wood.com> writes:
>>
>> > What you are missing is that if the recv ever returns no bytes at all
>> > then the other end has closed the connection.  So something like this
>> > is the correct thing to write :-
>> >
>> >   data = ""
>> >   while True:
>> >       new = client.recv(256)
>> >       if not new:
>> >           break
>> >       data += new
>>
>>  This is a good case for the iter() function:
>>
>>  buf = cStringIO.StringIO()
>>  for new in iter(partial(client.recv, 256), ''):
>>      buf.write(new)
>>  data = buf.getvalue()
>>
>>  Note that appending to a string is almost never a good idea, since it
>>  can result in quadratic allocation.
>
>My aim was clear exposition rather than the ultimate performance!
>
>Anyway str += was optimised in python 2.4 or 2.5 (forget which) wasn't
>it?  I'm not convinced it will be any worse performing than
>cStringIO.StringIO.write() which effectively appends to a string in
>exactly the same way.
>
>This test agrees with me!
>
>$ python -m timeit -s 's = ""' 'for i in xrange(100000): s+="x"'
>10 loops, best of 3: 23.8 msec per loop
>
>$ python -m timeit -s 'from cStringIO import StringIO; s=StringIO()' 'for i in xrange(100000): s.write("x")'
>10 loops, best of 3: 56 msec per loop
>

It's a bit nice that using cStringIO doesn't rely on a very esoteric
optimization in the CPython eval loop, as well as on what references
happen to exist to what objects.  For example, one might want to use a
debugger without falling back to the quadratic behavior of repeated
string concatenation.  cStringIO wins out in this case.

Jean-Paul



More information about the Python-list mailing list