On Wednesday, August 27, 2014 6:56:59 PM UTC+2, Guido van Rossum wrote:
>
> On Tue, Aug 26, 2014 at 2:04 AM, Martin Richard <[email protected] 
> <javascript:>> wrote:
>>
>>
>> I would have thought that the backlog argument would have been used only 
>> when host and port are provided. But since it's not the case, maybe it 
>> should only be possible to set backlog=None, and in this case, don't 
>> perform the call to listen. I am not a huge fan of this solution, but it 
>> would not break compatibility.
>>
>
> It's the best I am willing to do.
>  
>
>> My use case is that the process executing python code will "borrow" a 
>> socket from its parent: a process will create a listening socket and the 
>> program written in python will inherit it via fork/exec. While it's 
>> probably possible to pass the backlog value via a command line argument to 
>> the child (for instance), it's not convenient nor really make sense (for 
>> the sake of separation of concerns).
>>
>
> Ah, understood. Is there no ioctl you can use to obtain the current 
> backlog, so you could pass that to create_server()? After all it's a bit of 
> a special case.
>

Not that I know of, unfortunately. The solution I chose was subclass 
socket.socket and make listen() a no-op, it works thanks to the fileno 
argument of socket(). 

>  
>
>>   
>>>
>>>> > I also have questions about StreamWriter and the flow control system. 
>>>>> > 
>>>>> > I understood that I am expected to yield from writer.drain() after 
>>>>> any call 
>>>>> > to writer.write(), so the flow control mechanism can make the 
>>>>> calling task 
>>>>> > wait until the buffer gets downsized to the low-water limit. 
>>>>>
>>>>> Nope, see the documentation: 
>>>>>
>>>>> "drain(): 
>>>>> Wait until the write buffer of the underlying transport is flushed." 
>>>>>  
>>>>>
>>>> > I don't 
>>>>> > understand why the writer.write[lines]() functions are not 
>>>>> coroutines which 
>>>>> > actually yield from writer.drain(), nor why the "yield from 
>>>>> writer.drain()" 
>>>>> > is not performed before the call to write(). 
>>>>>
>>>>> The purpose of a buffer is performances. You may be able to pack 
>>>>> multiple small writes into a single call to socket.send(). Flushing 
>>>>> after each call to stream.write() would call socket.send() each time, 
>>>>> which is less efficient. 
>>>>>
>>>>  
>>>> That is what the documentation says, but it's almost a contradiction 
>>>> with the next sentence: I fail to understand why it doesn't wait if the 
>>>> protocol is not paused. The protocol will only be paused if the buffer 
>>>> reaches the high water limit, thus, drain() will indeed not wait for the 
>>>> underlying buffer to be flushed in most cases.
>>>> If this is true, I also don't get how we can be notified that the 
>>>> high-water limit has been reached using StreamWriter(). If as a user i 
>>>> keep 
>>>> calling write(), I can always fill my buffer without knowing that the 
>>>> other 
>>>> end can not keep up.
>>>>
>>>
>>> Right. The situation where you aren't required to call drain() is pretty 
>>> specific, but it is also pretty common -- it is for those situations where 
>>> the nature of your application implies that you won't be writing a lot of 
>>> data before you have a natural point where your code yields anyway. For 
>>> example in an http client there's probably a pretty low practical limit 
>>> (compared to the typical buffer size) of the size of all headers combined, 
>>> so you won't need to drain() between headers, even if you use a separate 
>>> write() call for each header. (However, once you are sending unlimited 
>>> data, e.g. a request body, you should probably insert drain() calls.)
>>>
>>> So the guideline is, if you call write() in an unbounded loop that 
>>> doesn't contain yield-from, you should definitely call drain(); if you call 
>>> write() just a few times with bounded data, you don't need to bother.
>>>
>>> FWIW, there is a subtle API usability issue that made me design write() 
>>> this way. A lot of code calls write() without checking for the return 
>>> value, so if write() was a coroutine, forgetting to add "yield from" in 
>>> front of a write() call would be pretty painful to debug. Input calls don't 
>>> have this problem (at least not to the same extent) -- you rarely call 
>>> read() or readline() without immediately doing something with the result, 
>>> so if you forget the yield-from with one of these your code will most 
>>> likely crash instead of being silent or hanging.
>>>  
>>>
>>
>> Maybe this is because I'm not experienced enough with network 
>> programming, but while it makes sense, it's a bit hard to understand how 
>> one is supposed to use drain() when reading the doc or the code. I will 
>> probably propose a patch to the documentation explaining how to use 
>> drain(). 
>>
>
> That will be much appreciated!
>

I filed a bug with a patch here: http://bugs.python.org/issue22348 :)

Cheers,
Martin

Reply via email to