调试asyncio
asyncio中内置了几个有用的调试功能。
首先,事件循环在运行时使用日志来发送状态消息。如果在应用程序中启用日志记录,则其中的一些功能可用。其他的可以通过告诉循环发出更多的调试消息来打开。调用set_debug()传递布尔值,指示是否应该启用调试。
因为构建在asyncio上的应用程序对贪婪的协程不交出控制权高度敏感,因此有支持检测事件循环内置的慢回调。通过启用调试来打开它,并通过将循环的slow_callback_duration属性设置为发出警告的秒数来控制定义的“slow”。
最后,如果使用asyncio的应用程序退出而没有清除一些协程或其他资源,这可能意味着有一个逻辑错误阻止了一些应用程序代码的运行。启用ResourceWarning警告会导致在程序退出时报告这些情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import argparse import asyncio import logging import sys import time import warnings parser = argparse.ArgumentParser('debugging asyncio') parser.add_argument( '-v', dest='verbose', default=False, action='store_true', ) args = parser.parse_args() logging.basicConfig( level=logging.DEBUG, format='%(levelname)7s: %(message)s', stream=sys.stderr, ) LOG = logging.getLogger('') async def inner(): LOG.info('inner starting') time.sleep(0.1) LOG.info('inner completed') async def outer(loop): LOG.info('outer starting') await asyncio.ensure_future(loop.create_task(inner())) LOG.info('outer completed') event_loop = asyncio.get_event_loop() if args.verbose: LOG.info('enabling debugging') event_loop.set_debug(True) event_loop.slow_callback_duration = 0.001 warnings.simplefilter('always', ResourceWarning) LOG.info('entering event loop') event_loop.run_until_complete(outer(event_loop))
|
在未启用调试的情况下运行时,此应用程序一切正常。
1 2 3 4 5 6 7 8
| $ python3 asyncio_debug.py DEBUG: Using selector: KqueueSelector INFO: entering event loop INFO: outer starting INFO: inner starting INFO: inner completed INFO: outer completed
|
开启调试暴露了它的一些问题,事实上虽然inner()已经完成,但是这比设置的slow_callback_duration需要更多的时间,并且程序退出时事件循环未被正确关闭。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $ python3 asyncio_debug.py -v DEBUG: Using selector: KqueueSelector INFO: enabling debugging INFO: entering event loop INFO: outer starting INFO: inner starting INFO: inner completed WARNING: Executing <Task finished coro=<inner() done, defined at asyncio_debug.py:34> result=None created at asyncio_debug.py:44> took 0.102 seconds INFO: outer completed .../lib/python3.5/asyncio/base_events.py:429: ResourceWarning: unclosed event loop <_UnixSelectorEventLoop running=False closed=False debug=True> DEBUG: Close <_UnixSelectorEventLoop running=False closed=False debug=True>
|
本文翻译自《The Python3 Standard Library By Example》asyncio相关章节