Create custom async context managers
Recently I found myself trying to set up some code to mimic some functionality of Depends
from FaspAPI in other async code. After a few false starts, I found the asynccontextmanager
helper from contextlib
, which made the process a breeze.
It’s super helpful for quickly creating your own context manager wrappers, all you need
is an (async) function that yield
’s once
import os
from contextlib import asynccontextmanager
import httpx
headers = httpx.Headers(
{
'Content-Type': 'application/json',
'Authorization': f'Bearer {os.environ["MY_TOKEN"]}',
}
)
base_url = 'https://example.com/api/'
@asynccontextmanager
async def custom_client() -> httpx.AsyncClient:
async with httpx.AsyncClient(
base_url=base_url,
headers=headers,
) as client:
yield client
async def function_using_using_client(thing_id: int) -> dict:
async with custom_client() as client:
r = await client.get(f'/thing/{thing_id}')
r.raise_for_status()
return r.json()
For synchronous versions it’s basically the same, just remove all instances of async
and await
.
This example could be extended to enable reuse of a single global client at scale via a singleton pattern