ブロッキング/ノンブロッキング

ブロッキング

  • 処理が終了するまで待つ

  • 待っている間はほかの処理を行えない

time.sleep はブロッキングするので、完了を待ってから次の処理に移る

 1import asyncio
 2import time
 3
 4
 5async def neru(n):
 6    time.sleep(n)
 7
 8
 9async def main():
10    await asyncio.create_task(neru(2))
11    await asyncio.create_task(neru(5))
12
13
14start = time.time()
15asyncio.run(main(), debug=True)
16print(f"time: {time.time() - start}")

実行結果: time: 7.009732246398926

ノンブロッキング

  • ブロッキングされない

  • ほかの処理ができる

asyncio.sleep はノンブロッキング処理なので、待っている間に次の処理に移れる

 1import asyncio
 2import time
 3
 4
 5async def main():
 6    await asyncio.create_task(asyncio.sleep(2))
 7    await asyncio.create_task(asyncio.sleep(5))
 8
 9
10start = time.time()
11asyncio.run(main())
12print(f"time: {time.time() - start}")

実行結果: time: 5.004534006118774

ノンブロッキング関数の実装

 1import asyncio
 2import time
 3
 4
 5async def neru(n):
 6    loop = asyncio.get_running_loop()
 7    loop.run_in_executor(None, time.sleep, n)
 8
 9
10async def main():
11    await asyncio.create_task(neru(3))
12    await asyncio.create_task(neru(5))
13
14
15start = time.time()
16asyncio.run(main())
17print(f"time: {time.time() - start}")

実行結果: time: 5.005532503128052

練習問題

次のコードを非同期(ノンブロッキング)に実装してください

 1import time
 2import urllib.request
 3
 4
 5def _get_status_code(url):
 6    with urllib.request.urlopen(url) as res:
 7        return res.status
 8
 9
10def get_status_code(cor_name, n):
11    url = f"https://httpbin.org/delay/{n}"
12    http_status = _get_status_code(url)
13    print(f"{cor_name}: {http_status}")
14
15
16def main():
17    get_status_code("cor1", 2)
18    get_status_code("cor2", 5)
19
20
21start = time.time()
22main()
23print(f"time: {time.time() - start}")