Asynchronous I/O isn’t new in Python. Since Python 3.4, asyncio is part of the standard library. From A simple introduction to Python’s asyncio and I quote here:
Asyncio is all about writing asynchronous programs in Python. Asyncio is a beautiful symphony between an Event loop, Tasks and Coroutines all coming together so perfectly.
I agree and I love the pluggable event loop model. Asynchronous I/O isn’t unique to Python. I have been using libuv recently, a multi-platform C library focusing on Asynchronous I/O, and it has a very similar concept. I am really excited to find uasyncio
libraries in the micrypython-lib GitHub repository. More interestingly, uasyncio
is installed by default in the MicroPython official ESP8266 and ESP32 firmware as frozen modules. Here is a very simple example on MicroPython uasyncio
to get started. Peter Hinch has a more complete tutorial.
Build MicroPython Binary
You don’t really need a micro controller to start using MicroPython. It has Unix and Windows ports that can run natively on you systems but you might have to build it yourself. You don’t need to build MicroPython Unix port yourself if your system supports Snap apps (see below).
micropython-src/ports/unix$ make axtls # needed until v1.9.4
micropython-src/ports/unix$ make
If everything goes well, you will find a single micropython
binary in the same folder. You can start it from there or copy it to your system path.
Install micropython-uasyncio Library
The Unix port has a handy package management utility upip
installed by default.
$ micropython -m upip install micropython-uasyncio
Library files will be copied to $PATH/.micropython/lib
. Alternatively, you can download them directly from the micrypython-lib GitHub repository.
Create Asynchronous Tasks
Python asyncio
are built on cooperative multi-tasking and generators. MicroPython implements the entire Python 3.4 syntax with additionaly async
/ await
keywords from Python 3.5.
async def sleep_5sec():
while True:
print('sleep 5 seconds')
await uasyncio.sleep(5)
We can create other tasks like sleeping longer or making requests to backend REST APIs. It feels more natural to me to program in Asynchronous I/O model. Each task is a relatively small piece of code to finish one job and we hook them together in an event loop.
Wire Tasks in An Event Loop
You can get the singleton event loop instance from uasyncio
, attach tasks, and call run_forever
to give control to the scheduler.
import uasyncio
async def sleep_5sec():
while True:
print('sleep 5 seconds')
await uasyncio.sleep(5)
async def sleep_7sec():
while True:
print('sleep 7 seconds')
await uasyncio.sleep(7)
if __name__ == '__main__':
loop = uasyncio.get_event_loop()
loop.create_task(sleep_5sec()) # schedule asap
loop.create_task(sleep_7sec())
loop.run_forever()
This example is trivial and might not be very interesting. Peter Hinch has more useful demo programs in his tutorial. In this PyCon AU 2018, Matt Trentini also had a quick 20-minute talk on Asyncio in (Micro)Python to explain the basic concepts.
Updated on November 24, 2018
I have created an unofficial MicroPython Unix port Snap app. To test the latest successful build on your device, please run:
$ sudo snap install micropython