10.5.15 用asyncio调试
asyncio中内置了很多有用的调试特性。例如,事件循环使用logging在它运行时生成状态消息。其中一些消息在应用启用日志记录时就可以得到;要得到另外一些消息,需要显式地告诉循环生成更多的调试消息。可以调用set_debug()并传入一个布尔值指示是否启用调试。
由于基于asyncio建立的应用对不能交出控制的贪婪协程非常敏感,所以事件循环中内置了相应的支持来检测慢回调。可以通过启用调试打开这个特性,将循环的slow_callback_duration属性设置为一个秒数(在这个时间之后要发出一个警告)以控制"慢"的定义。
最后如果一个使用asyncio的应用退出时没有清理一些协程或其他资源,那么这种行为可能说明存在一个逻辑错误组织了一些应用代码运行。启用ResourceWarning警告会在程序退出时报告这些情况。
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')
# Use a blocking sleep to simulate
# doing work inside the function.
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')
# Enable debugging.
event_loop.set_debug(True)
# Make the threshold for "slow" tasks very very small for
# illustration.The default is 0.1,or 100 milliseconds.
event_loop.slow_callback_duration = 0.001
# Reprot all mistakes managing asynchronous resources.
warnings.simplefilter('always',ResourceWarning)
LOG.info('entering event loop')
event_loop.run_until_complete(outer(event_loop))
运行时如果没有启用调试,那么看起来这个应用一切正常。
运行结果:
不过,打开调试就会暴露出应用中存在的一些问题。例如,尽管inner()能完成,但是它花费的时间要大于所设置的slow_callback_duration。另外,程序退出时事件循环没有妥善地关闭。
运行结果: