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
