#python #compsci #software 

Used for [[Asynchronous programming|asynchronous programming]]

## High-level APIs
### Runners
"Runners" are high-level asyncio primitives that are used to run asyncio code.
They are built on top of an event loop with the aid to simplify async code usage for common wide-spread scenarios.

![[Pasted image 20250802182307.png]]
([[Coroutine]])

![[Pasted image 20250802182943.png]]
Methods:
![[Pasted image 20250802183032.png]]

### Coroutines and Tasks
#### Coroutines
Coroutines declared with the **async/await** syntax is the preferred way of writing asyncio applications.:
![[Pasted image 20250802183212.png]]

To actually run a coroutine, asyncio provides the following mechanisms:
![[Pasted image 20250802183244.png]]

with the `asyncio.create_task()` function you can run coroutines concurrently (not really - we're not multithreading, BUT in here "concurrently" means that if one of the tasks waits or idles, the other task starts) as asyncio Tasks. Using the previous example:
![[Pasted image 20250802183327.png]]

The `asyncio.TaskGroup` class provides  a more modern alternative to `create_task()`:
![[Pasted image 20250802183403.png]] ^256deb


#### Awaitables
We say that an object is an **awaitable** object if it can be used in an `await` expression, which itself can only be used INSIDE a coroutine (async function).
3 types of awaitable objects:
- coroutines
- Tasks
- Futures

![[Pasted image 20250802183539.png]]
![[Pasted image 20250802183559.png]]
![[Pasted image 20250802183611.png]]
#### Creating Tasks
![[Pasted image 20250802185054.png]]

#### Task Cancellation
![[Pasted image 20250802185127.png]]

#### Task Groups
![[Pasted image 20250802185219.png]]
![[Pasted image 20250802185344.png]]
![[Pasted image 20250802185431.png]]
![[Pasted image 20250802185514.png]]

![[Pasted image 20250802190049.png]]

#### Sleeping
![[Pasted image 20250802190412.png]]
#### Running Tasks Concurrently
![[Pasted image 20250802190510.png]]
![[Pasted image 20250802190554.png]]

#### Eager Task Factory
Eager Task Execution = tasks start as soon as they are called
![[Pasted image 20250802190739.png]]
![[Pasted image 20250802190904.png]]


#### Shielding from cancellation
![[Pasted image 20250802191015.png]]

#### Timeouts
![[Pasted image 20250802191136.png]]
![[Pasted image 20250802191219.png]]
![[Pasted image 20250802191231.png]]
![[Pasted image 20250802191305.png]]

#### Waiting Primitives
![[Pasted image 20250802191404.png]]
![[Pasted image 20250802191504.png]]


#### Running in Threads
![[Pasted image 20250802191540.png]]


#### Scheduling from other Threads
![[Pasted image 20250802191723.png]]

#### Introspection
![[Pasted image 20250802191907.png]]

#### Task Object
![[Pasted image 20250802193027.png]]
Methods:
![[Pasted image 20250802193604.png]]
![[Pasted image 20250802193613.png]]
![[Pasted image 20250802193624.png]]
![[Pasted image 20250802193704.png]]
![[Pasted image 20250802194410.png]]
![[Pasted image 20250802194612.png]]
![[Pasted image 20250802194620.png]]

### Streams
Streams are high-level async/await-ready primitives to work with network connections. Streams allow sending and receiving data without using callbacks or low-level protocols and transports.

#### Stream Functions
![[Pasted image 20250802223844.png]]
![[Pasted image 20250802223854.png]]

![[Pasted image 20250802223904.png]]

#### Stream Reader
![[Pasted image 20250802223950.png]]
![[Pasted image 20250802224001.png]]

#### StreamWriter
![[Pasted image 20250802224019.png]]
![[Pasted image 20250802224039.png]]
![[Pasted image 20250802224102.png]]
#### Examples
![[Pasted image 20250802224144.png]]
![[Pasted image 20250802224157.png]]
![[Pasted image 20250802224215.png]]
![[Pasted image 20250802224227.png]]
(uses [[socket module]])

### Syncronization primitives
![[Pasted image 20250802225153.png]]

asyncio has the following basic synchronization primitives:
- Lock
- Event
- Condition
- Semaphore
- BoundedSemaphore
- Barrier

#### Lock
![[Pasted image 20250802225255.png]]
(thread-safe = will work even if many threads are executing it simultaneously)
![[Pasted image 20250802225343.png]]

essentially everything inside the lock context manager must be executed before anything else.

![[Pasted image 20250802225710.png]]
![[Pasted image 20250802225759.png]]

![[Pasted image 20250802225839.png]]![[Pasted image 20250802230005.png]]
![[Pasted image 20250802230047.png]]

#### Semaphore
![[Pasted image 20250802230214.png]]
![[Pasted image 20250802230226.png]]
#### Barrier
![[Pasted image 20250802230331.png]]
![[Pasted image 20250802230347.png]]
![[Pasted image 20250802230431.png]]