Simple Guide to Python Asyncio

Nov 19, 2020

Note

Refer [Threading vs Multiprocessing vs Asyncio]python3-threading-vs-multiprocessing-vs-asyncio

Asyncio is more lightweight than thread and suited for IO bound tasks, utilize single core only (concurrent but not parallel execution)

Multiple Process

import asyncioasync def run(name):    for i in range(10):        print(f"{name}", end='', flush=True)        await asyncio.sleep(0.5)    print(f"{name}[END]", end='', flush=True)async def main():    tasks = [run('a'), run('b'), run('c')]    # wait for all task to finish    await asyncio.gather(*tasks)asyncio.run(main())print('[STOP]')
abcabcabcabcabcabcabcabcabcabca[END]b[END]c[END][STOP]

Add Tasks Dynamically

  • Launch new tasks dynamically (one by one over time)
  • Quit when all tasks finished
import asyncioasync def run(name):    for i in range(10):        print(f"{name}", end='', flush=True)        await asyncio.sleep(0.2)    print(f"{name}[END]", end='', flush=True)async def main():    tasks = []    task_names = ['a', 'b', 'c']    while True:        try:            name = task_names.pop(0)            if name:                task = asyncio.create_task(run(name))                tasks.append(task)        except IndexError:            pass        done, pending = await asyncio.wait(tasks, timeout=1)        for _task in done:            # sometimes fake done, forever wait block            # await _task            if _task.done():                # need this to show exception                try:                    print('result', _task.result())                except Exception as e:                    print(e)        if not pending:            break    print('main[END]', end='', flush=True)asyncio.run(main())print('[STOP]')

Shared Value

Since asyncio run on single Thread/CPU concurrently (not in parallel), it is safe to share value.

Increment a counter value. Using array or class object as mutable type; if you pass in integer (immutable type), it will just be a local value of each coroutines).

import asyncioasync def run(name, count):    for i in range(10):        await asyncio.sleep(0.5)        count[0] += 1        print(f"{name}[{count[0]}]", end='', flush=True)    print(f"{name}[END]", end='', flush=True)async def main():    count = [0]    tasks = [run('a', count), run('b', count), run('c', count)]    # wait for all task to finish    await asyncio.gather(*tasks)asyncio.run(main())print('[STOP]')
a[1]b[2]c[3]a[4]b[5]c[6]a[7]b[8]c[9]a[10]b[11]c[12]a[13]b[14]c[15]a[16]b[17]c[18]a[19]b[20]c[21]a[22]b[23]c[24]a[25]b[26]c[27]a[28]a[END]b[29]b[END]c[30]c[END][STOP]

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.