
Using the async with Statement
Using the async with Statement 관련


The with
statement also has an asynchronous version, async with
. You can use it to write context managers that depend on asynchronous code. It’s quite common to see async with
in that kind of code, as many IO operations involve setup and teardown phases.
For example, say you need to code an asynchronous function to check if a given site is online. To do that, you can use aiohttp
, asyncio
, and async with
like this:
import aiohttp
import asyncio
async def check(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
print(f"{url}: status -> {response.status}")
html = await response.text()
print(f"{url}: type -> {html[:17].strip()}")
async def main():
await asyncio.gather(
check("https://realpython.com"),
check("https://pycoders.com"),
)
asyncio.run(main())
Here’s what this script does:
- Line 3 imports
aiohttp
, which provides an asynchronous HTTP client and server forasyncio
and Python. Note thataiohttp
is a third-party package that you can install by runningpython -m pip install aiohttp
on your command line. - Line 4 imports
asyncio
, which allows you to write concurrent code using theasync
andawait
syntax. - Line 6 defines
check()
as an asynchronous function using theasync
keyword.
Inside check()
, you define two nested async with
statements:
- Line 7 defines an outer
async with
that instantiatesaiohttp.ClientSession()
to get a context manager. It stores the returned object insession
. - Line 8 defines an inner
async with
statement that calls.get()
onsession
usingurl
as an argument. This creates a second context manager and returns aresponse
. - Line 9 prints the response status code for the
url
at hand. - Line 10 runs an awaitable call to
.text()
onresponse
and stores the result inhtml
. - Line 11 prints the site
url
and its document type,doctype
. - Line 13 defines the script’s
main()
function, which is also a coroutine. - Line 14 calls
gather()
fromasyncio
. This function runs awaitable objects in a sequence concurrently. In this example,gather()
runs two instances ofcheck()
with a different URL for each. - Line 19 runs
main()
usingasyncio.run()
. This function creates a newasyncio
event loop and closes it at the end of the operation.
If you run this script from your command line, then you get an output similar to the following:
python site_checker_v0.py
#
# https://realpython.com: status -> 200
# https://pycoders.com: status -> 200
# https://pycoders.com: type -> <!doctype html>
# https://realpython.com: type -> <!doctype html>
Cool! Your script works and you confirm that both sites are currently available. You also retrieve the information regarding document type from each site’s home page.
Note
Your output can look slightly different due to the nondeterministic nature of concurrent task scheduling and network latency. In particular, the individual lines can come out in a different order.
The async with
statement works similar to the regular with
statement, but it requires an asynchronous context manager. In other words, it needs a context manager that is able to suspend execution in its enter and exit methods. Asynchronous context managers implement the special methods .__aenter__()
and .__aexit__()
, which correspond to .__enter__()
and .__exit__()
in a regular context manager.
The async with ctx_mgr
construct implicitly uses await ctx_mgr.__aenter__()
when entering the context and await ctx_mgr.__aexit__()
when exiting it. This achieves async
context manager behavior seamlessly.