#+TITLE: AsyncIO In Depth

# Outline: https://kinopio.club/asyncio-outline-IVepJwzB8cuYaVvA-HeVQ

If you find Python's async / await to be mostly easy to use, yet
somewhat magical and opaque I think you'll find this series of
articles valuable. I spent several weeks digging into asyncio's
internals and these articles are the result of my exploration.

They aren't a way to quickly become productive with asyncio: this
series is the one you should read after you can write a little bit of
async code, but aren't quite sure how or why things work.

This is an in-progress depth-first-traversal into the Python's
event loop implementation. After several aborted attempts at writing
about asyncio in 2020, I'm  publishing this as a series in pieces
instead of trying to complete the full and then sharing.[fn:taocp]

Part of my exploration last year also involved building and open
sourcing Panopticon -- a Python tracer to visualize async execution,
so I'll also touch upon that along the way, with some other projects I
have in mind.

As far as possible, I'll also be describing how I went about
spelunking into asyncio along the way as well.

#+CAPTION: Several attempts at writing about AsyncIO
#+begin_src sh :results output verbatim
tree ~/expLog/src/drafts/asyncio
#+end_src

#+RESULTS:
#+begin_example
/home/knl/expLog/src/drafts/asyncio
├── asyncio
│   ├── eventloops.org
│   └── index.org
├── asyncio.org
├── asyncioscheduler.org
├── asyncioterms.org
├── eventloop.org
├── python.org
└── tracingasyncio.org

1 directory, 8 files
#+end_example

[fn:taocp]: I have the infinitesimally smallest possible inkling of
what Don Knuth's life must be like.

# TODO Potentially insert a discussion on event loops here, just to
# set context and create the same mental image.

* Hello, world!
I'll use a classical program and make it slightly more interesting and
asynchronous, to have a simple program to dissect throughout the
series.

There's nothing very complex here: I just tweaked our favorite program
to simulate a reasonably proficient typist.

../static/images/hello.gif

#+begin_src python :results output 
import asyncio
import random

async def hello_world():
    for ch in "Hello, world!":
        x = max(0, random.gauss(.08, .03))
        await asyncio.sleep(x)
        print(ch, end="", flush=True)
    print()
   
asyncio.run(hello_world())
#+end_src
#+RESULTS:
: Hello, world!

For comparison, I'll also contrast it against a far more boring and
synchronous version of the program:
#+begin_src python :results output
import random
import time

def sync_hello_world():
    for ch in "Hello, world!":
        x = max(0, random.gauss(.08, .03))
        time.sleep(x)
        print(ch, end="", flush=True)
    print()

sync_hello_world()
#+end_src

#+RESULTS:
: Hello, world!

* Tentative Table of Contents
** async 
** Coroutine objects
** await
** asyncio
*** asyncio.sleep
** The Event loop
** The Scheduler
** epoll
** Generators
** Async Generators
** Coroutine classes
** Design patterns