非同期コンテキストマネージャーとイテレーター
async with と async for のプロトコルを実装します。
「非同期コンテキストマネージャーとイテレーター」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
async with文
セットアップや後処理でI/Oのawaitが必要なコンテキストマネージャーには、async withを使用します。管理対象のオブジェクトは__aenter__と__aexit__を実装する必要があります。
import asyncio
class AsyncFile:
async def __aenter__(self):
print("open")
return self
async def __aexit__(self, *args):
print("close")
async def main():
async with AsyncFile() as f:
print("using")
asyncio.run(main())__aenter__と__aexit__
どちらもコルーチンです。入場時には__aenter__がawaitされ、例外が発生した場合でも退場時には__aexit__がawaitされます。
import asyncio
class DBSession:
async def __aenter__(self):
self.conn = await async_connect()
return self.conn
async def __aexit__(self, exc_type, exc_val, exc_tb):
if exc_type:
await self.conn.rollback()
else:
await self.conn.commit()
await self.conn.close()
return False@asynccontextmanager
contextlib.asynccontextmanagerを使用すると、非同期ジェネレーター関数として非同期コンテキストマネージャーを記述できます。
from contextlib import asynccontextmanager
import asyncio
@asynccontextmanager
async def managed_resource():
print("acquire")
try:
yield {"status": "ready"}
finally:
print("release")
async def main():
async with managed_resource() as r:
print(r["status"])
asyncio.run(main())async for文
async forは非同期イテラブル(__aiter__と__anext__を実装するオブジェクト)を反復処理します。各反復でI/Oが発生する場合があります。
import asyncio
class AsyncCounter:
def __init__(self, n): self.n, self.i = n, 0
def __aiter__(self): return self
async def __anext__(self):
if self.i >= self.n: raise StopAsyncIteration
await asyncio.sleep(0)
self.i += 1
return self.i
async def main():
async for val in AsyncCounter(3):
print(val)
asyncio.run(main())非同期ジェネレーター
yieldを含むasync def関数は、非同期ジェネレーターです。これを利用するにはasync forを使用します。
import asyncio
async def ticker(n):
for i in range(n):
await asyncio.sleep(1)
yield i
async def main():
async for val in ticker(3):
print(val) # 0, 1, 2 with 1-s pauses
asyncio.run(main())非同期ファイルI/Oのためのaiofiles
aiofilesライブラリは、ファイル操作を非同期コンテキストマネージャーおよび非同期イテレーターとしてラップします。
# pip install aiofiles
import aiofiles, asyncio
async def main():
async with aiofiles.open("data.txt", "r") as f:
async for line in f:
print(line.strip())aiohttpクライアントセッション
aiohttp.ClientSessionは、HTTPリクエストを並行して実行するための非同期コンテキストマネージャーです。
# pip install aiohttp
import aiohttp, asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.json()
asyncio.run(fetch("https://api.example.com/data"))複数の非同期コンテキストマネージャー
1行に複数のasync with節を連ねることができます(Python 3.10以降の括弧形式)。
import asyncio
async def main():
async with (
open_db() as db,
open_cache() as cache,
):
data = await db.fetch("SELECT 1")
await cache.set("key", data)AsyncExitStack
contextlib.AsyncExitStackは、動的な集合の非同期コンテキストマネージャーを管理します。
from contextlib import AsyncExitStack
import asyncio
async def main():
async with AsyncExitStack() as stack:
conn1 = await stack.enter_async_context(connect("db1"))
conn2 = await stack.enter_async_context(connect("db2"))
await process(conn1, conn2)pytest-asyncioで非同期コードをテストする
pytest-asyncioを使用すると、@pytest.mark.asyncioマーカーを付けて非同期テスト関数を記述できます。
# pip install pytest-asyncio
import pytest, asyncio
async def fetch(): return 42
@pytest.mark.asyncio
async def test_fetch():
result = await fetch()
assert result == 42非同期イテレーター・プロトコルのまとめ
非同期イテラブルとは、__aiter__を持つオブジェクトです。非同期イテレーターとは、それに加えて__anext__も持つオブジェクトです。非同期ジェネレーターは、これら両方を自動的に実装します。
import asyncio
async def gen():
yield 1
yield 2
async def main():
g = gen()
print(await g.__anext__()) # 1
print(await g.__anext__()) # 2確認問題
async withで使用するには、オブジェクトがどのダンダーメソッドを実装する必要がありますか。
まとめ
非同期のセットアップや後処理が必要なリソースにはasync withを使用します。非同期に値を生成するイテラブルにはasync forを使用します。非同期ジェネレーターを使うと、非同期イテレーターの作成を簡略化できます。aiofilesやaiohttpなどのライブラリは、非同期ネイティブなファイル操作やHTTP操作を提供します。
よくある質問
「非同期コンテキストマネージャーとイテレーター」レッスンは無料ですか?
はい。「非同期コンテキストマネージャーとイテレーター」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「非同期コンテキストマネージャーとイテレーター」で何を学びますか?
async with と async for のプロトコルを実装します。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「非同期コンテキストマネージャーとイテレーター」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- コルーチンとイベントループ
- await、タスク、ギャザリング
- 非同期コンテキストマネージャーとイテレーター
- 本番環境での非同期 I/O パターン