是否有任何 linter 可以检测异步函数中的阻塞调用?

Ane*_*pic 10 pylint python-3.x flake8 python-asyncio

https://www.aeracode.org/2018/02/19/python-async-simplified/

如果您调用非阻塞同步函数,则不会破坏您的一天,如下所示:

def get_chat_id(name):
    return "chat-%s" % name

async def main():
    result = get_chat_id("django")
Run Code Online (Sandbox Code Playgroud)

但是,如果您调用阻塞函数(例如 Django ORM),则异步函数内的代码看起来是相同的,但现在它是危险的代码,可能会阻塞整个事件循环,因为它不等待:

def get_chat_id(name):
    return Chat.objects.get(name=name).id

async def main():
    result = get_chat_id("django")
Run Code Online (Sandbox Code Playgroud)

您可以看到,如果程序员没有超级了解调用它的所有内容,那么很容易让一个非阻塞函数“意外地”变成阻塞。这就是为什么我建议您在没有安全执行或事先不知道它是非阻塞标准库函数(例如os.path.join.

所以我正在寻找一种方法来自动捕获此错误的实例。Python 是否有任何 linter 会将异步函数内的同步函数调用报告为违规?

我可以配置 Pylint 或 Flake8 来执行此操作吗?

我不一定介意它是否也捕获了上面的第一种情况(这是无害的)。


更新:

在某种程度上,我意识到这是一个愚蠢的问题,正如米哈伊尔的回答所指出的那样。我们需要的是 linter 应该检测到的“危险同步函数”的定义。

因此,出于这个问题的目的,我给出以下定义:

“危险同步函数”是执行 IO 操作的函数。例如,这些操作必须由 gevent 进行猴子修补,或者必须包装在async函数中,以便事件循环可以进行上下文切换。

(我欢迎对这个定义的任何改进)

Mik*_*mov 6

所以我正在寻找一种方法来自动捕获此错误的实例。

让我们澄清一些事情:文章中讨论的错误是当您在某个 asyncio 协程中调用任何长时间运行的同步函数时(它可以是 I/O 阻塞调用,也可以只是具有大量计算的纯 CPU 函数)。这是一个错误,因为它会阻止整个事件循环,从而导致性能显着下降(此处有更多相关信息,包括答案下面的评论)。

有什么办法可以自动捕获这种情况吗?在运行时之前 - 不,除了您之外没有人可以预测特定函数是否需要 10 秒或 0.01 秒来执行。在运行时它已经内置了 asyncio,您所要做的就是启用调试模式。

如果您担心某些同步函数可能会在长时间运行(在调试模式下的运行时可检测到)和短时运行(不可检测)之间变化,只需使用run_in_executor在后台线程中执行函数- 它将保证事件循环不会被阻塞。