<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Fri, 15 Jun 2018 at 09:18, Michel Desmoulin <<a href="mailto:desmoulinmichel@gmail.com">desmoulinmichel@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> <br>
> The strict API compatibility requirements of core Python stdlib, coupled<br>
> with the very long feature release life-cycles of Python, make me think<br>
> this sort of thing perhaps is better built in an utility library on top<br>
> of asyncio, rather than inside asyncio itself?  18 months is a long long<br>
> time to iterate on these features.  I can't wait for Python 3.8...<br>
>  <br>
<br>
A lot of my late requests come from my attempt to group some of that in<br>
a lib: <a href="https://github.com/Tygs/ayo" rel="noreferrer" target="_blank">https://github.com/Tygs/ayo</a><br></blockquote><div><br></div><div>Ah, good idea.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Most of it works, although I got read of context() recently, but the<br>
lazy task part really fails.<br>
<br>
<br>
Indeed, the API allows to do:<br>
<br>
        async with ayo.scope() as run:<br>
            task_list = run.all(foo(), foo(), foo())<br>
            run.asap(bar())<br>
            await task_list.gather()<br>
            run.asap(baz())<br>
<br>
<br>
<br>
scope() return a nursery like object, and this works perfectly, with the<br>
usual guaranty of Trio's nursery, but working in asyncio right now.<br></blockquote><div><br></div><div>To be honest, I see "<span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">async with" being abused everywhere in asyncio, lately.  I like to have objects with start() and stop() methods, but everywhere I see async context managers.</span></div><div><br></div><div>Fine, add nursery or whatever, but please also have a simple start() / stop() public API.</div><div><br></div><div>"async with" is only good for functional programming.  If you want to go more of an object-oriented style, you tend to have start() and stop() methods in your classes, which will call start() & stop() (or close()) methods recursively on nested resources.  So of the libraries (aiopg, I'm looking at you) don't support start/stop or open/close well.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
However, I tried to add to the mix:<br>
<br>
        async with ayo.scope(max_concurrency=2) as run:<br>
            task_list = run.all(foo(), foo(), foo())<br>
            run.asap(bar())<br>
            await task_list.gather()<br>
            run.asap(baz())<br>
<br>
And I can get it to work. task_list will right now contains a list of<br>
tasks and None, because some tasks are not scheduled immediately. That's<br>
why I wanted lazytasks. I tried to create my own lazy tasks, but it<br>
never really worked. I'm going to try to go down the road of wrapping<br>
the unscheduled coro in a future-like object as suggested by Yuri. But<br>
having that built-in seems logical, elegant, and just good design in<br>
general: __init__ should not have side effects.<br></blockquote><div><br></div><div>I tend to slightly agree, but OTOH if asyncio had been designed to not schedule tasks automatically on __init__ I bet there would have been other users complaining that "why didn't task XX run?", or "why do tasks need a start() method, that is clunky!".  You can't please everyone...</div><div><br></div><div>Also, in</div><div> <span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">            task_list = run.all(foo(), foo(), foo())</span><br style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><br></span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">As soon as you call <span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">foo(),<span> you are instantiating a coroutine, which consumes memory, while the task may not even be scheduled for a long time (if you have 5000 potential tasks but only execute 10 at a time, for example).</span></span></span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span><br></span></span></span></div><div><span style="background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span style="text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><span>But if you do as Yuri suggested, you'll instead accept a function reference, foo, which is a singleton, you can have many foo references to the function, but they will only create coroutine objects when the task is actually about to be scheduled, so it's more efficient in terms of memory.</span></span></span></div><div><br></div></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">Gustavo J. A. M. Carneiro<div>Gambit Research<br>"The universe is always one step beyond logic." -- Frank Herbert</div></div></div></div>