Python asyncioã³ã«ãŒãã³ããããã°ããããã®å æ¬çãªã¬ã€ããçµã¿èŸŒã¿ã®ãããã°ã¢ãŒãã䜿çšããŠãäžè¬çãªéåæããã°ã©ãã³ã°ã®åé¡ãç¹å®ããŠè§£æ±ºããæ¹æ³ãåŠã³ãŸãã
Pythonã³ã«ãŒãã³ãããã°ïŒAsyncioãããã°ã¢ãŒãã®ç¿åŸ
Pythonã®asyncio
ã䜿çšããéåæããã°ã©ãã³ã°ã¯ãç¹ã«I/OããŠã³ãã®æäœã«ãããŠãããã©ãŒãã³ã¹äžã®å€§ããªå©ç¹ãæäŸããŸãããã ããéåæã³ãŒãã®ãããã°ã¯ããã®éç·åœ¢ãªå®è¡ãããŒã®ããã«å°é£ãªå ŽåããããŸããPythonã¯ããããã°ããã»ã¹ã倧å¹
ã«ç°¡çŽ åã§ããasyncio
çšã®çµã¿èŸŒã¿ãããã°ã¢ãŒããæäŸããŠããŸãããã®ã¬ã€ãã§ã¯ãasyncio
ãããã°ã¢ãŒãã广çã«äœ¿çšããŠãéåæã¢ããªã±ãŒã·ã§ã³ã«ãããäžè¬çãªåé¡ãç¹å®ãã解決ããæ¹æ³ã説æããŸãã
éåæããã°ã©ãã³ã°ã®èª²é¡ãçè§£ãã
ãããã°ã¢ãŒãã«å ¥ãåã«ãéåæã³ãŒãã®ãããã°ã«ãããäžè¬çãªèª²é¡ãçè§£ããããšãéèŠã§ãã
- éç·åœ¢å®è¡: éåæã³ãŒãã¯é çªã«å®è¡ãããŸãããã³ã«ãŒãã³ã¯ã€ãã³ãã«ãŒãã«å¶åŸ¡ãæ»ããããå®è¡ãã¹ã远跡ããããšãå°é£ã«ãªããŸãã
- ã³ã³ããã¹ãã¹ã€ããã³ã°: ã¿ã¹ã¯éã®é »ç¹ãªã³ã³ããã¹ãã¹ã€ããã³ã°ã¯ããšã©ãŒã®åå ãäžæçã«ããå¯èœæ§ããããŸãã
- ãšã©ãŒäŒæ: ããã³ã«ãŒãã³ã®ãšã©ãŒãåŒã³åºãå ã®ã³ã«ãŒãã³ã§ããã«æããã«ãªããšã¯éãããæ ¹æ¬åå ãç¹å®ããããšãå°é£ã«ãªããŸãã
- ç«¶åç¶æ : è€æ°ã®ã³ã«ãŒãã³ãåæã«ã¢ã¯ã»ã¹ããå ±æãªãœãŒã¹ã¯ãç«¶åç¶æ ãåŒãèµ·ãããäºæž¬äžå¯èœãªåäœã«ã€ãªããå¯èœæ§ããããŸãã
- ãããããã¯: ã³ã«ãŒãã³ãäºãã«ç¡æéã«åŸ æ©ãããšããããããã¯ãçºçããã¢ããªã±ãŒã·ã§ã³ã忢ããå¯èœæ§ããããŸãã
Asyncioãããã°ã¢ãŒãã®ç޹ä»
asyncio
ãããã°ã¢ãŒãã¯ãéåæã³ãŒãã®å®è¡ã«é¢ãã貎éãªæŽå¯ãæäŸããŸããæ¬¡ã®æ©èœããããŸãã
- 詳现ãªãã®ã³ã°: ã³ã«ãŒãã³ã®äœæãå®è¡ããã£ã³ã»ã«ãããã³äŸå€åŠçã«é¢é£ããããŸããŸãªã€ãã³ãããã°ã«èšé²ããŸãã
- ãªãœãŒã¹èŠå: æªéãã®ãœã±ãããæªéãã®ãã¡ã€ã«ãããã³ãã®ä»ã®ãªãœãŒã¹ãªãŒã¯ãæ€åºããŸãã
- äœéã³ãŒã«ããã¯æ€åº: æå®ããããããå€ãããé·ãå®è¡ãããã³ãŒã«ããã¯ãç¹å®ããæœåšçãªããã©ãŒãã³ã¹ã®ããã«ããã¯ã瀺ããŸãã
- ã¿ã¹ã¯ãã£ã³ã»ã«è¿œè·¡: ã¿ã¹ã¯ãã£ã³ã»ã«ã«é¢ããæ å ±ãæäŸããã¿ã¹ã¯ããã£ã³ã»ã«ãããçç±ãšãã¿ã¹ã¯ãæ£ããåŠçãããŠãããã©ãããçè§£ããã®ã«åœ¹ç«ã¡ãŸãã
- äŸå€ã³ã³ããã¹ã: ã³ã«ãŒãã³å ã§çºçããäŸå€ã«å¯ŸããŠããå€ãã®ã³ã³ããã¹ããæäŸãããšã©ãŒããã®ãœãŒã¹ãŸã§ç°¡åã«è¿œè·¡ã§ããããã«ããŸãã
Asyncioãããã°ã¢ãŒãã®æå¹å
asyncio
ãããã°ã¢ãŒãã¯ãããã€ãã®æ¹æ³ã§æå¹ã«ã§ããŸãã
1. PYTHONASYNCIODEBUG
ç°å¢å€æ°ã䜿çšãã
ãããã°ã¢ãŒããæå¹ã«ããæãç°¡åãªæ¹æ³ã¯ãPythonã¹ã¯ãªãããå®è¡ããåã«ãPYTHONASYNCIODEBUG
ç°å¢å€æ°ã1
ã«èšå®ããããšã§ãã
export PYTHONASYNCIODEBUG=1
python your_script.py
ããã«ãããã¹ã¯ãªããå šäœã®ãããã°ã¢ãŒããæå¹ã«ãªããŸãã
2. asyncio.run()
ã§ãããã°ãã©ã°ãèšå®ãã
ã€ãã³ãã«ãŒããéå§ããããã«asyncio.run()
ã䜿çšããŠããå Žåã¯ãdebug=True
åŒæ°ãæž¡ãããšãã§ããŸãã
import asyncio
async def main():
print("Hello, asyncio!")
if __name__ == "__main__":
asyncio.run(main(), debug=True)
3. loop.set_debug()
ã䜿çšãã
ã€ãã³ãã«ãŒãã€ã³ã¹ã¿ã³ã¹ãååŸããset_debug(True)
ãåŒã³åºãããšã«ãã£ãŠããããã°ã¢ãŒããæå¹ã«ããããšãã§ããŸãã
import asyncio
async def main():
print("Hello, asyncio!")
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.set_debug(True)
loop.run_until_complete(main())
ãããã°åºåã®è§£é
ãããã°ã¢ãŒããæå¹ã«ãªããšãasyncio
ã¯è©³çްãªãã°ã¡ãã»ãŒãžãçæããŸãããããã®ã¡ãã»ãŒãžã¯ãã³ã«ãŒãã³ã®å®è¡ã«é¢ãã貎éãªæ
å ±ãæäŸããŸãã以äžã«ãäžè¬çãªãããã°åºåã®çš®é¡ãšãã®è§£éæ¹æ³ã瀺ããŸãã
1. ã³ã«ãŒãã³ã®äœæãšå®è¡
ãããã°ã¢ãŒãã¯ãã³ã«ãŒãã³ãäœæããã³éå§ããããšãã«ãã°ã«èšé²ããŸããããã¯ãã³ã«ãŒãã³ã®ã©ã€ããµã€ã¯ã«ã远跡ããã®ã«åœ¹ç«ã¡ãŸãã
asyncio | execute () running at example.py:3>
asyncio | Task-1: created at example.py:7
ãã®åºåã¯ãTask-1
ãšããååã®ã¿ã¹ã¯ãexample.py
ã®7è¡ç®ã§äœæãããçŸåš3è¡ç®ã§å®çŸ©ãããã³ã«ãŒãã³a()
ãå®è¡ããŠããããšã瀺ããŠããŸãã
2. ã¿ã¹ã¯ã®ãã£ã³ã»ã«
ã¿ã¹ã¯ããã£ã³ã»ã«ããããšããããã°ã¢ãŒãã¯ãã£ã³ã»ã«ã€ãã³ããšãã£ã³ã»ã«ã®çç±ããã°ã«èšé²ããŸãã
asyncio | Task-1: cancelling
asyncio | Task-1: cancelled by () running at example.py:10>
ããã¯ãTask-1
ãTask-2
ã«ãã£ãŠãã£ã³ã»ã«ãããããšã瀺ããŠããŸããã¿ã¹ã¯ã®ãã£ã³ã»ã«ãçè§£ããããšã¯ãäºæããªãåäœãé²ãããã«éèŠã§ãã
3. ãªãœãŒã¹èŠå
ãããã°ã¢ãŒãã¯ããœã±ããããã¡ã€ã«ãªã©ãéããããŠããªããªãœãŒã¹ã«ã€ããŠèŠåããŸãã
ResourceWarning: unclosed
ãããã®èŠåã¯ãããã©ãŒãã³ã¹ã®äœäžãã·ã¹ãã ã®äžå®å®ã«ã€ãªããå¯èœæ§ã®ãããªãœãŒã¹ãªãŒã¯ãç¹å®ããŠä¿®æ£ããã®ã«åœ¹ç«ã¡ãŸãã
4. äœéã³ãŒã«ããã¯æ€åº
ãããã°ã¢ãŒãã§ã¯ãæå®ããããããå€ãããé·ãå®è¡ãããã³ãŒã«ããã¯ãæ€åºã§ããŸããããã¯ãããã©ãŒãã³ã¹ã®ããã«ããã¯ãç¹å®ããã®ã«åœ¹ç«ã¡ãŸãã
asyncio | Task was destroyed but it is pending!
pending time: 12345.678 ms
5. äŸå€åŠç
ãããã°ã¢ãŒãã¯ãã³ã«ãŒãã³å ã§çºçããäŸå€ã«å¯ŸããŠãäŸå€ãçºçããã¿ã¹ã¯ãã³ã«ãŒãã³ãªã©ãããå€ãã®ã³ã³ããã¹ããæäŸããŸãã
asyncio | Task exception was never retrieved
future: () done, raised ValueError('Invalid value')>
ãã®åºåã¯ãTask-1
ã§ValueError
ãçºçããé©åã«åŠçãããªãã£ãããšã瀺ããŠããŸãã
Asyncioãããã°ã¢ãŒãã䜿çšãããããã°ã®å®è·µçãªäŸ
asyncio
ãããã°ã¢ãŒãã䜿çšããŠäžè¬çãªåé¡ã蚺æããå®è·µçãªäŸãããã€ãèŠãŠã¿ãŸãããã
1. æªéãã®ãœã±ããã®æ€åº
ãœã±ãããäœæããŠãé©åã«éããªã次ã®ã³ãŒããæ€èšããŠãã ããã
import asyncio
import socket
async def handle_client(reader, writer):
data = await reader.read(100)
message = data.decode()
addr = writer.get_extra_info('peername')
print(f"Received {message!r} from {addr!r}")
print(f"Send: {message!r}")
writer.write(data)
await writer.drain()
# Missing: writer.close()
async def main():
server = await asyncio.start_server(
handle_client,
'127.0.0.1',
8888
)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
if __name__ == "__main__":
asyncio.run(main(), debug=True)
ãããã°ã¢ãŒããæå¹ã«ããŠãã®ã³ãŒããå®è¡ãããšãéããããŠããªããœã±ããã瀺ãResourceWarning
ã衚瀺ãããŸãã
ResourceWarning: unclosed
ãããä¿®æ£ããã«ã¯ãããšãã°ãhandle_client
ã³ã«ãŒãã³ã«writer.close()
ã远å ããŠawaitããããšã«ããããœã±ãããé©åã«éããããŠããããšã確èªããå¿
èŠããããŸãã
writer.close()
await writer.wait_closed()
2. äœéã³ãŒã«ããã¯ã®ç¹å®
äœéãªæäœãå®è¡ããã³ã«ãŒãã³ããããšããŸãã
import asyncio
import time
async def slow_function():
print("Starting slow function")
time.sleep(2)
print("Slow function finished")
return "Result"
async def main():
task = asyncio.create_task(slow_function())
result = await task
print(f"Result: {result}")
if __name__ == "__main__":
asyncio.run(main(), debug=True)
ããã©ã«ãã®ãããã°åºåã§ã¯äœéãªã³ãŒã«ããã¯ãçŽæ¥ç¹å®ãããŸããããæ éãªãã®ã³ã°ããã³ãããã¡ã€ãªã³ã°ããŒã«ïŒcProfileãpy-spyãªã©ïŒãšçµã¿åãããããšã§ãã³ãŒãã®äœéãªéšåãçµã蟌ãããšãã§ããŸããæœåšçã«é ãæäœã®ååŸã«ã¿ã€ã ã¹ã¿ã³ãããã°ã«èšé²ããããšãæ€èšããŠãã ãããæ¬¡ã«ãcProfileãªã©ã®ããŒã«ã䜿çšããŠããã°ã«èšé²ããã颿°åŒã³åºãã§ããã«ããã¯ãåé¢ã§ããŸãã
3. ã¿ã¹ã¯ãã£ã³ã»ã«ã®ãããã°
ã¿ã¹ã¯ãäºæãããã£ã³ã»ã«ãããã·ããªãªãæ€èšããŠãã ããã
import asyncio
async def worker():
try:
while True:
print("Working...")
await asyncio.sleep(0.5)
except asyncio.CancelledError:
print("Worker cancelled")
async def main():
task = asyncio.create_task(worker())
await asyncio.sleep(2)
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Task cancelled in main")
if __name__ == "__main__":
asyncio.run(main(), debug=True)
ãããã°åºåã«ã¯ãã¿ã¹ã¯ããã£ã³ã»ã«ãããããšã瀺ãããŸãã
asyncio | execute started at example.py:16>
Working...
Working...
Working...
Working...
asyncio | Task-1: cancelling
Worker cancelled
asyncio | Task-1: cancelled by result=None>
Task cancelled in main
ããã«ãããã¿ã¹ã¯ãmain()
ã³ã«ãŒãã³ã«ãã£ãŠãã£ã³ã»ã«ãããããšã確èªãããŸããexcept asyncio.CancelledError
ãããã¯ã䜿çšãããšãã¿ã¹ã¯ãå®å
šã«çµäºããåã«ã¯ãªãŒã³ã¢ããã§ããããããªãœãŒã¹ãªãŒã¯ãççŸããç¶æ
ãé²ãããšãã§ããŸãã
4. ã³ã«ãŒãã³ã§ã®äŸå€åŠç
é©åãªäŸå€åŠçã¯ãéåæã³ãŒãã§ã¯éåžžã«éèŠã§ããæªåŠçã®äŸå€ãå«ã次ã®äŸãæ€èšããŠãã ããã
import asyncio
async def divide(x, y):
return x / y
async def main():
result = await divide(10, 0)
print(f"Result: {result}")
if __name__ == "__main__":
asyncio.run(main(), debug=True)
ãããã°ã¢ãŒãã¯ãæªåŠçã®äŸå€ãå ±åããŸãã
asyncio | Task exception was never retrieved
future: result=None, exception=ZeroDivisionError('division by zero')>
ãã®äŸå€ãåŠçããã«ã¯ãtry...except
ãããã¯ã䜿çšã§ããŸãã
import asyncio
async def divide(x, y):
return x / y
async def main():
try:
result = await divide(10, 0)
print(f"Result: {result}")
except ZeroDivisionError as e:
print(f"Error: {e}")
if __name__ == "__main__":
asyncio.run(main(), debug=True)
ããã§ãäŸå€ããã£ãããããæ£åžžã«åŠçãããŸãã
Asyncioãããã°ã®ãã¹ããã©ã¯ãã£ã¹
asyncio
ã³ãŒãããããã°ããããã®ãã¹ããã©ã¯ãã£ã¹ãããã€ã瀺ããŸãã
- ãããã°ã¢ãŒããæå¹ã«ãã: éçºããã³ãã¹ãäžã¯ãåžžã«ãããã°ã¢ãŒããæå¹ã«ããŠãã ããã
- ãã®ã³ã°ã䜿çšãã: ã³ã«ãŒãã³ã«è©³çްãªãã®ã³ã°ã远å ããŠãå®è¡ãããŒã远跡ããŸããasyncioåºæã®ã€ãã³ãã«ã¯
logging.getLogger('asyncio')
ã䜿çšããã¢ããªã±ãŒã·ã§ã³åºæã®ããŒã¿ã«ã¯ç¬èªã®ãã¬ãŒã䜿çšããŸãã - äŸå€ãåŠçãã: æªåŠçã®äŸå€ãã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ãããã®ãé²ãããã«ãå ç¢ãªäŸå€åŠçãå®è£ ããŸãã
- ã¿ã¹ã¯ã°ã«ãŒãã䜿çšãã (Python 3.11以é): ã¿ã¹ã¯ã°ã«ãŒãã¯ãé¢é£ããã¿ã¹ã¯ã®ã°ã«ãŒãå ã§ã®äŸå€åŠçãšãã£ã³ã»ã«ãç°¡çŽ åããŸãã
- ã³ãŒãããããã¡ã€ãªã³ã°ãã: ãããã¡ã€ãªã³ã°ããŒã«ã䜿çšããŠãããã©ãŒãã³ã¹ã®ããã«ããã¯ãç¹å®ããŸãã
- åäœãã¹ããäœæãã: ã³ã«ãŒãã³ã®åäœãæ€èšŒããããã«ã培åºçãªåäœãã¹ããäœæããŸãã
- åãã³ãã䜿çšãã: åãã³ããæŽ»çšããŠãåé¢é£ã®ãšã©ãŒãæ©æã«æ€åºããŸãã
- ãããã¬ãŒã®äœ¿çšãæ€èšãã:
pdb
ãIDEãããã¬ãŒãªã©ã®ããŒã«ã䜿çšããŠãasyncioã³ãŒããã¹ãããå®è¡ã§ããŸãããã ããéåæå®è¡ã®æ§è³ªäžãæ³šææ·±ããã®ã³ã°ã䜿çšãããããã°ã¢ãŒãããã广ãäœãããšããããããŸãã
é«åºŠãªãããã°ãã¯ããã¯
åºæ¬çãªãããã°ã¢ãŒããè¶ ããŠããããã®é«åºŠãªãã¯ããã¯ãæ€èšããŠãã ããã
1. ã«ã¹ã¿ã ã€ãã³ãã«ãŒãããªã·ãŒ
ã«ã¹ã¿ã ã€ãã³ãã«ãŒãããªã·ãŒãäœæããŠãã€ãã³ããã€ã³ã¿ãŒã»ããããŠãã°ã«èšé²ã§ããŸããããã«ããããããã°ããã»ã¹ãããã«çްããå¶åŸ¡ã§ããŸãã
2. ãµãŒãããŒãã£ã®ãããã°ããŒã«ã®äœ¿çš
ããã€ãã®ãµãŒãããŒãã£ã®ãããã°ããŒã«ã¯ãasyncio
ã³ãŒãã®ãããã°ã«åœ¹ç«ã¡ãŸããæ¬¡ã«äŸã瀺ããŸãã
- PySnooper: ã³ãŒãã®å®è¡ãèªåçã«ãã°ã«èšé²ãã匷åãªãããã°ããŒã«ã
- pdb++: 匷åãããæ©èœãåããæšæºã®
pdb
ãããã¬ãŒã®æ¹è¯çã - asyncio_inspector: asyncioã€ãã³ãã«ãŒããæ€æ»ããããã«ç¹å¥ã«èšèšãããã©ã€ãã©ãªã
3. ã¢ã³ããŒããã (泚æããŠäœ¿çš)
極端ãªå Žåã¯ããããã°ã®ç®çã§ã¢ã³ããŒãããã䜿çšããŠasyncio
颿°ã®åäœã倿Žã§ããŸãããã ããããã¯åŸ®åŠãªãã°ãçºçããããã³ãŒãã®ä¿å®ãé£ãããªã£ããããå¯èœæ§ããããããæ³šæããŠè¡ãå¿
èŠããããŸããããã¯éåžžã絶察ã«å¿
èŠã§ãªãéãæšå¥šãããŸããã
çµè«
éåæã³ãŒãã®ãããã°ã¯é£ããå ŽåããããŸãããasyncio
ãããã°ã¢ãŒãã¯ãããã»ã¹ãç°¡çŽ åããããã®è²ŽéãªããŒã«ãšæŽå¯ãæäŸããŸãããããã°ã¢ãŒããæå¹ã«ããåºåãè§£éãããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãéåæã¢ããªã±ãŒã·ã§ã³ã«ãããäžè¬çãªåé¡ã广çã«ç¹å®ããŠè§£æ±ºããããå
ç¢ã§ããã©ãŒãã³ã¹ã®é«ãã³ãŒããäœæã§ããŸããæé«ã®çµæãåŸãã«ã¯ããããã°ã¢ãŒãããã®ã³ã°ããããã¡ã€ãªã³ã°ãããã³åŸ¹åºçãªãã¹ããšçµã¿åãããããšãå¿ããªãã§ãã ãããç·Žç¿ãšé©åãªããŒã«ã䜿çšãããšãasyncio
ã³ã«ãŒãã³ã®ãããã°æè¡ãç¿åŸããã¹ã±ãŒã©ãã«ã§å¹ççã§ä¿¡é Œæ§ã®é«ãéåæã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã