Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for async for, async with #12

Open
klange opened this issue Apr 17, 2021 · 6 comments
Open

Add support for async for, async with #12

klange opened this issue Apr 17, 2021 · 6 comments

Comments

@klange
Copy link
Collaborator

klange commented Apr 17, 2021

No description provided.

@p-i-
Copy link

p-i- commented Mar 29, 2022

When implementing async, please examine trio (https://trio.readthedocs.io/en/stable/reference-core.html)

asyncio is clumsy and ugly in many ways. It evolved as Python async paradigm evolved, and is full of legacy gotchas.

trio is clean as a whistle, and has an active gitter community (with the creator active). There's no active community for asyncio.

@klange
Copy link
Collaborator Author

klange commented Mar 29, 2022

This ticket is about implementing required syntax support in the compiler. Did you mean to post your shill on #6?

@p-i-
Copy link

p-i- commented Apr 2, 2022

Probably. My intent was to make sure kuroko core-devs are aware of the merits of Trio.
I have no dog in this race. I get no reward from my keystrokes beyond the hope that maybe the intel is useful.
So if I am "shill"ing, it is from my experience as a pure mathematician turned s/w dev and experience of using both async libs.

@klange
Copy link
Collaborator Author

klange commented Apr 5, 2022

Sorry, that was harsh of me, I've grown a bit paranoid about issue comments and seeing someone whose profile lists them as a C-level posting about an external product trips some alarms for me.

This would be better discussed on #6 as previously stated, but to provide a more reasonable response: I'm in a tough position here. Even if asyncio is maligned in the Python world, if compatibility is my aim then providing the interface is something that may need to happen even if there are "better" options to emulate. Either way, from the examples I saw in Trio, support the async syntax constructs describe in this ticket is still necessary.

I should also note that Kuroko is still mostly a personal project; while I'm happy to accept external contributions, I haven't quite garnered a team yet, core or otherwise, and that's likely to be the biggest blocker in closing the gap on Python 3.x compatibility.

@p-i-
Copy link

p-i- commented Apr 5, 2022

huh, so GitHub examines my repos and estimates my language skillset.
It didn't occur to me that this creates a certain public image. 90%+ of of my code is not on my personal GitHub.

Yes, I see it is an awkward situation to be in... I once wrote a Python / C++ interop (https://github.com/p-i-/picxx) and got so carried away with making it "fully featured" that I completely forgot my original task 😂 .

There's a problem: Trio await returns an object incompatible with asyncio await.

https://github.com/python-trio/trio-asyncio is required to "shim" one to t'other.

So an async function containing asyncio awaits is "asyncio-flavour", similarly for "trio-flavour".
And you can't mix different flavour awaits inside a given async function.
If you want to await a trio-flavour function inside an asyncio-flavour one, you'd need something like:

from trio_asyncio import trio_as_aio
def my_aio_flavour(...):
    await some_aio(...)
    await trio_as_aio(my_trio_flavour, *args)
    await some_other_aio(...)

As I remember, you can also:

@trio_as_aio
def my_aio_flavour(...):
    await my_trio_flavour_1(...)
    await my_trio_flavour_2(...)

This might look like an unwanted extra layer of headfuck, but my thinking in the original post was that the internal architecture of Trio might serve as a better foundation / core-mechanic for implementing async, and that an asyncio compat layer could simply shim on top of this.

The key intel I wanted to provide was that the primary Trio architect (Nathaniel J Smith) looked at the whole Python asyncio machinery, and built Trio from the ground up with 20/20 hindsight.

It may be possible to "lift" trio and trio_asyncio directly into kuroko, and shim an asyncio compat layer on top of this, and save reinventing a tricky wheel. It is likely that Nathaniel J Smith (and Trio community) would be happy to assist exploring the possibility on the Trio gitter. He's (/they've) been extremely helpful in helping me solve problems that are much less worthy than your own work.

I haven't explored the internals of either Trio or asyncio, but my experience from using both was that Trio required only a small fraction of the cognitive effort of asyncio to achieve any particular task.

I'll sign off at this point, as I don't think I have anything valuable to contribute beyond this observation.

@klange
Copy link
Collaborator Author

klange commented Apr 5, 2022

huh, so GitHub examines my repos and estimates my language skillset.
It didn't occur to me that this creates a certain public image. 90%+ of of my code is not on my personal GitHub.

What? No, you say in your bio you're a CEO.

There's a problem: Trio await returns an object incompatible with asyncio await.

await is syntax supported by the compiler, not something a library controls - it's really just a fancy yield from that works in the context of an async function.

And none of this has much to do with async for and async with...

CPython bytecode for a simple async function with an await:

async def foo():
     await bar()
Disassembly of <code object foo at 0x7f57ffaff5b0, file "<dis>", line 2>:
  3           0 LOAD_GLOBAL              0 (bar)
              2 CALL_FUNCTION            0
              4 GET_AWAITABLE
              6 LOAD_CONST               0 (None)
              8 YIELD_FROM
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

Kuroko's bytecode of the same:

<foo() from <stdin>>
   2        0 GET_GLOBAL          0 'bar'
            2 CALL                0
            4 INVOKE_AWAIT          
            5 NONE                  
      >>    6 YIELD_FROM          4 (to 13)
            9 YIELD                 
           10 LOOP                7 (to 6)
      >>   13 POP                   
           14 NONE                  
           15 RETURN       

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants