Pythonで非同期関数を定義する(async def, Python 3.5以降)
この記事では、Python 3.5以降で導入された非同期関数`async def`の使い方を解説します。非同期処理の基本的な概念、`async`と`await`キーワードの使い方、そして具体的な使用例を示します。
目次
非同期関数とは?
非同期関数とは、IOバウンドな処理(ネットワーク通信、ファイル読み込みなど)を並行的に実行することで、プログラム全体の処理時間を短縮するための関数です。`async def`キーワードを使って定義します。
従来の同期処理では、処理が完了するまで次の処理に進めませんが、非同期処理では、処理を開始したら次の処理に進み、処理が完了したら結果を取得します。そのため、複数のIOバウンドな処理を同時に実行できるため効率的です。
async defキーワード
`async def`キーワードを使って非同期関数を定義します。通常の関数定義`def`と似ていますが、`async`キーワードが付いている点が異なります。
import asyncio
async def my_async_function():
print('非同期関数の中です')
await asyncio.sleep(1) # 1秒待つ
print('非同期関数が完了しました')
この例では、`asyncio.sleep(1)`で1秒間処理を一時停止します。この間、他の非同期処理を実行できます。
awaitキーワード
`await`キーワードは、非同期関数の呼び出しに使用します。`await`の後に続く非同期関数が完了するまで、処理を一時停止します。
async def main():
await my_async_function()
asyncio.run(main())
非同期関数の呼び出し
非同期関数は、`asyncio.run()`関数を使って呼び出します。`asyncio.run()`関数は、イベントループを開始し、非同期関数を処理します。
import asyncio
async def my_async_function():
# ...
async def main():
await my_async_function()
asyncio.run(main())
awaitと同期処理との違い
awaitを使うことで、非同期関数の中で同期的に処理を待つことができます。awaitがないと、非同期関数はすぐに次の処理に進みます。
import asyncio
async def async_func():
print('async_func開始')
await asyncio.sleep(2)
print('async_func終了')
async def main():
print('main開始')
await async_func()
print('main終了')
asyncio.run(main())
# 出力結果:
# main開始
# async_func開始
# async_func終了
# main終了
この例では、`await async_func()`によって`main`関数は`async_func`関数が完了するまで待ちます。もし`await`がないと、`main`関数は`async_func`関数が完了する前に`main終了`を出力します。
エラー処理
非同期関数内でのエラー処理は、`try...except`ブロックで行います。
import asyncio
async def my_async_function():
try:
# エラーが発生する可能性のある処理
result = await some_async_operation()
except Exception as e:
print(f'エラーが発生しました: {e}')
return None
return result
実践例:非同期で複数のWebサイトにアクセスする
複数のWebサイトに同時にアクセスしてHTMLを取得する例です。`aiohttp`ライブラリを使用します。
import asyncio
import aiohttp
async def fetch_html(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
tasks = [
fetch_html(session, 'https://www.example.com'),
fetch_html(session, 'https://www.google.com'),
]
results = await asyncio.gather(*tasks)
for result in results:
print(result[:100]) # 先頭100文字だけ表示
asyncio.run(main())
関連記事
- Pythonで非同期処理を使う(asyncio, Python 3.5以降)
- Pythonでコルーチンを使う(asyncio, Python 3.5以降)
- PythonでFuture・Taskを使う(asyncio, Python 3.5以降)
- Pythonでaiohttpを使って非同期HTTPリクエストを送信 (Python 3.5以降)
- Pythonでジェネレータ関数を使う(yield)
- Pythonで関数に型ヒントをつける (Python 3.5以降)
- Pythonで関数を定義(def)
- Pythonで高階関数を使う(map, filter, reduceなど)
- Pythonでデコレータ関数を使う
- Pythonで再帰関数を使う