if __name__ wraps the app. The app calls Handler. Handler may create_task a worker. The contract — names, lists, exceptions — links into Handler. Pan down: concurrency catalog, then the loop as a pipeline, with the traps crossed out. Click Handler, Accept, or if invoice:.
Click a shape or a question
Questions this tree answers
A request · one Task per accept · cancel is not optional
Types · lists · exceptions
names · objects
lists · dicts
except · with · venv
__main__ → app → handler
Operation
Library
Methods · protocols
GIL · one Task per request
Call frame
Heap / refcount
list header
PyObject header
GC / cycles
Concurrency catalog
asyncio · bound
queue · process
cancel · lock
typing · io
Loop — pipeline and traps
Task created → drain
don’t · advanced last
ientryif __name__ == "__main__"
runtime dials after import
irejectedclass Api(FastAPI)
is-a · not the model
don’t subclass
irouterFastAPI / APIRouter
routes · two children
Handler + library · not nested
ioperationasync def create
validate · save · return
one Task for this request
iwritereturn Response
status then body
no extra Task
iside pathcreate_task fanout
after commit
must still cancel
ilibraryinvoice.save
domain · not main
tests import this
sibling of Handler, not a child
iruntimepython / uvicorn starts
after import
you do not dial
iwrongside effects on import
not how a process starts
tests call the library
inoneNone · True · 0 · ""
bound is valid
unbound is NameError
ibindx = v · LEGB
name → object
inner x = is a new local
iidentityis · == · id()
same object vs equal
None with is
itrapdef f(xs=[])
one list for every call
None + assign inside
irecordclass Invoice
__init__ · __dict__
names alias objects
methods hang off this
iheaderlist · pointers + overalloc
array of refs
slice copies pointers
igrowxs.append(x)
returns None
+= mutates a list
ifixed(a, b) · comma
structure, not a grow API
(1,) needs the comma
ihashd[k] · .get
KeyError vs None
not a concurrent map
itextstr · bytes · encode
len is characters
bytes at the edge
immutable
idefdef f(a, *, k=None)
*args · **kwargs
hints are not runtime
iLIFOwith lock:
enter now · exit on leave
async with in async
ipathexcept InvoiceError
not a return value
visible branch
icauseraise Wrap() from e
__cause__ walks
bare raise keeps tb
iforbiddenexcept: pass
hides KeyboardInterrupt
map, don’t hide
iAPI__all__ · public names
convention · not capital
import is cached
itabledef test_save
parametrize · fixtures
import the library
iidentityvenv · lock file
isolate the interpreter
lock what you run
iinstancedef save(self)
mutates the same object
no value receiver
iclasscls vs shared state
class var is one for all
keep instance data on self
ihas-aclass Store(Protocol)
structural, not is-a
icontractif it has save()
implicit · keep it small
itrapif invoice:
empty is not missing
inarrowisinstance(x, T)
except / match preferred
iTaskTask · coroutine
frame · parked or running
not an OS thread
ithreadThread · OS
must hold the GIL for bytecode
I/O may drop it
iGILGIL · one bytecode
serializes Python, not your invariant
not a Task cap
iframecreate() frame
locals die on return
unless something retains
recursion still capped
iheapInvoice on the heap
always a PyObject
refcount zero frees now
cache keeps it live
iheaderob_item · size · allocated
pointer array
objects elsewhere
alias shares the list
iheaderPyObject { refcnt, type }
every value starts here
None is a singleton
calls go through type
ieligiblerefcount 0 or cycle
zero frees now
a waiting Task still roots
imeasurepy-spy · tracemalloc
names the live set
don’t guess gc thresholds
istartasyncio.create_task
new Task · small frame
must be able to end
iboundSemaphore
max_workers
ceiling around tasks
ijoingather
wait all
does not bound
igroupTaskGroup
first error
cancels siblings
gather + cancel
imeetasyncio.Queue
put waits when full
maxsize is the cap
iI/Othreading.Thread
GIL · overlap I/O
join them
iCPUProcessPoolExecutor
pickle the args
new interpreter
iyieldawait
gives the loop a turn
missing await never ran
iproverbPass on a Queue
ownership moves
lock if already shared
irequesttimeout / cancel
CancelledError at await
don’t store tasks on the app
ilockasyncio.Lock
async with
not across blocking I/O
ibitasyncio.Event
one bit
not a job queue
ibridgeasyncio.to_thread
blocking call leaves the loop
not for CPU forever
ihintslist[T] · Protocol
checker, not runtime
not monomorphized
irecord@dataclass
default_factory
frozen · slots
ibytesopen · streams
with open
don’t block the loop
ilatelambda: i
lookup at call
freeze with default
i1 createNew Task
create_task · small frame
i2 readyLoop ready queue
coroutines that can run
i3 executeRun until await
create() body here
i4 wait I/Oawait socket / DB
task off the ready queue
i5 GILGIL drop / switch
I/O and C may release
a Python loop does not
i6 offloadto_thread / executor
blocking work leaves the loop
iparkawait Event / Queue
off the ready queue
must wake · timeout
idrainlifespan shutdown
stop accept · budget
no naked sys.exit
imapTask ≈ coroutine · Thread ≈ OS · GIL ≈ bytecode lock
create → ready → run → await → drain
GIL caps bytecode, not Tasks
iforbiddencreate_task in a million loop
no ceiling
pool instead
iforbiddencreate_task without cancel
leaks after the client goes
timeout or link it
iundefinedtwo tasks · one dict · await between
GIL ≠ the invariant
check-then-act is a race
iescape hatchctypes · cffi
lifetime is yours
almost never in Handler
iruntime typesinspect.signature
decode lives here
not the hot loop
72%
Click a box · three arrows off a layer are what it allows