【问题标题】:Build-time tool to check if async code path performs synchronous I/O用于检查异步代码路径是否执行同步 I/O 的构建时工具
【发布时间】:2020-07-17 20:31:34
【问题描述】:

假设我有以下程序

import requests

async def foo():
    res = await get_resource()
    status_code = await make_request(res)

    print(f"status code: {status_code}\n", res)

async def get_resource():
    # ...
    with open('file') as f:
        return f.read()

async def make_request(data):
    return requests.post('/create', data=data).status_code

这个程序从async 中得不到任何好处,并且会妨碍事件循环中其他代码的性能。显然,这是一个简单的示例,但跨多个文件和开发人员,可能并不那么容易发现。

如果我可以在我的构建管道中添加一些可以检测到这种情况的东西,那就太棒了。是否有任何 Python 构建工具会指示此异步代码正在请求同步 I/O?

【问题讨论】:

  • “会妨碍其他代码的性能”基于什么证据?我怀疑开销是否值得
  • 我的理解是通过调用同步代码,永远不会让其他异步代码。这是不正确的吗?无论如何,在我工作的代码库中,我们正在尝试隔离这条路径。
  • 哦,我看错了,如果它们不使用异步的东西,你想将操作更改为异步而不是将函数更改为非异步。是的,这会限制性能,但是您希望如何识别具有异步等效项的同步操作?就像文件 io 只有 3rd 方选项用于异步,所以任何识别它的构建工具都必须推荐一个特定的库,这使得它不那么通用。
  • 是的,我希望它能够静态分析这些。不过,这可能有点白日梦。
  • 好吧,我的意思是像编写代码来检查在 async 函数中使用 open 函数不会太难,只是想出一套可靠的规则来确定哪些函数应该替换它们需要替换的内容除了手动定义之外我看不到其他方法。

标签: python python-asyncio build-tools


【解决方案1】:

您可以使用 asyncio debug mode。除其他外,如果函数花费的时间超过 100 毫秒(可能会调整),它会显示日志消息:

WARNING: Executing <Task finished coro=<inner() done, defined at
asyncio_debug.py:33> result=None created at asyncio_debug.py:43>
took 0.101 seconds

【讨论】:

  • 很遗憾,不可行,也不一定能解决问题。这将需要分析测试运行,这可能无法捕捉到这些情况。静态分析是首选。
猜你喜欢
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多