New uasyncio version

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

New uasyncio version

Post by pythoncoder » Sun Nov 17, 2019 4:50 pm

A new version of uasyncio, completely rewritten by Damien, is imminent. This is discussed in PR5332 on GitHub. I have written a brief introduction to the key changes here.

tl;dr The version fixes major long standing bugs in uasyncio V2. It is a substantial simplification with improved asyncio compatibility. Many applications run unchanged. API changes are summarised in the introduction above.
Peter Hinch
Index to my micropython libraries.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: New uasyncio version

Post by kevinkk525 » Sun Nov 17, 2019 5:09 pm

Thank you for the introduction to the new uasyncio version Peter!
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

uCTRL
Posts: 47
Joined: Fri Oct 12, 2018 11:50 pm

Re: New uasyncio version

Post by uCTRL » Sun Nov 17, 2019 11:11 pm

Many applications run unchanged
Makes one wonder why compatibility with Cpython wasn't followed from the beginning?

Peter has done a good job in supporting this stuff with documentation and promotion.
But for someone like me that is not a proficient python programmer, understanding and dealing with asyncio has been a struggle.
Best illustrated in the following blog related to Cpython version.

http://lucumr.pocoo.org/2016/10/30/i-do ... d-asyncio/

from the blog:
Personal Thoughts

Man that thing is complex and it keeps getting more complex. I do not have the mental capacity to casually work with asyncio. It requires constantly updating the knowledge with all language changes and it has tremendously complicated the language. It's impressive that an ecosystem is evolving around it but I can't help but get the impression that it will take quite a few more years for it to become a particularly enjoyable and stable development experience.
The worst part is that asyncio is not even particularly fast. David Beazley's live demo hacked up asyncio replacement is twice as fast as it. There is an enormous amount of complexity that's hard to understand and reason about and then it fails on it's main promise. I'm not sure what to think about it but I know at least that I don't understand asyncio enough to feel confident about giving people advice about how to structure code for it.

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: New uasyncio version

Post by jimmo » Mon Nov 18, 2019 1:29 am

uCTRL wrote:
Sun Nov 17, 2019 11:11 pm
Makes one wonder why compatibility with Cpython wasn't followed from the beginning?
I think it took some experience with the problem to figure out whether this was even feasible in a "micro" way.
uCTRL wrote:
Sun Nov 17, 2019 11:11 pm
Best illustrated in the following blog related to Cpython version.
That post is 3 years old, and fortunately a lot of the things that were weird and confusing in the earlier days of asyncio have been addressed (some quite recently). The journey to asyncio involved a lot of complexity and there was a particularly difficult time (..well..about 3 years ago) where the transition from the "old style" (i.e. @coroutine and "yield from" etc) was still in progress and it was particularly intimidating to figure out how to do anything.

Nowadays, for most applications, you need a lot less knowledge of the internals (i.e. you can almost ignore the event loop completely).

But still, the main gotcha is of course trying to use asyncio in an existing non-async codebase. Your entire program, and all your io-based libraries need to be async-aware or you're going to have a hard time.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

It's getting simpler

Post by pythoncoder » Mon Nov 18, 2019 6:24 am

I think (u)asyncio has become steadily simpler to use. The history of asyncio is not pretty. It confused the hell out of me and I've been writing asynchronous code for nearly 40 years. One motive behind the tutorial was to suggest a programming style which ignored old redundant features. I will update it for the new version which is even simpler: as @jimmo points out, the Python 3.8 syntax embraced by the new version enables you to ignore the EventLoop.

Under the old version it was often possible to write code portable to asyncio and the style advocated in the tutorial facilitates portability. It was in the more "advanced" features like task cancellation where it diverged (and didn't really work properly). The old version largely reflected the state of asyncio at the time it was written.

For a complete beginner, getting your head round asynchronous programming is a paradigm shift. It is one well worth embracing as, for very good reasons, most serious firmware is written that way. The gurus will debate whether asyncio uses the best theoretical model. For us practical programmers the new syntax makes it easier to use than any other scheduler I've used.

Here is a script which flashes the LED's on a Pyboard 1.x asynchronously under the new version. To write this using synchronous code would be painful. What's more, if a Pyboard with 20 LED's came out, or for that matter to run it on a Pyboard D with only three LED's, you only need to change a single number. With synchronous code there would be substantial code changes.

Code: Select all

import pyb
import uasyncio as asyncio

async def killer(duration):
    await asyncio.sleep(duration)

async def toggle(objLED, time_ms):
    while True:
        await asyncio.sleep_ms(time_ms)
        objLED.toggle()

duration = 10  # Code runs for 10s
print("Flash LED's for {:3d} seconds".format(duration))
leds = [pyb.LED(x) for x in range(1,5)]  # Initialise all four on board LED's
for x, led in enumerate(leds):  # Create a Task for each LED
    t = int((0.2 + x/2) * 1000)  # Flash duration
    _ = asyncio.create_task(toggle(leds[x], t))
asyncio.run(killer(duration))
I don't think it can get much simpler than that ;)
Peter Hinch
Index to my micropython libraries.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: New uasyncio version

Post by kevinkk525 » Mon Nov 18, 2019 6:52 am

I also started with CPython asyncio with version 3.4 when it was first introduced and it was very confusing with @coroutine, yield from, then suddenly some await came along with Python3.5 but almost no good tutorials...
But I agree with jimmo and pythoncoder, asyncio came a long way and it is now very easy to use! Of course there will be complex scenarios and more advanced usage possibilities but especially for our use-case in micropython asyncio is very easy to use and extremely fast.
And with @pythoncoder's excellent tutorials it should be possible for every newcomer to easily get into asyncio without even looking at CPython tutorials. However, with this new version of uasyncio people can finally use CPython tutorials to write asyncio code for micropython! (Well except for the hardware parts that require micropython libraries like machine but @pythoncoder's tutorials explain those very well)
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
MostlyHarmless
Posts: 166
Joined: Thu Nov 21, 2019 6:25 pm
Location: Pennsylvania, USA

Re: New uasyncio version

Post by MostlyHarmless » Fri Nov 22, 2019 8:22 pm

uasyncio feels a lot like the Tcl/Tk event loop. Set up stuff to be called when things happen, then run "forever" ... love it!

Post Reply