有没有检测到异步函数中的阻塞调用的linter?

时间:2019-05-01 11:27:16

标签: python-3.x python-asyncio pylint flake8

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")
  

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

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

async def main():
    result = get_chat_id("django")
  

您会看到拥有一个非阻塞功能   如果程序员不是超级了解“偶然地”变得阻塞   一切都需要它。这就是为什么我建议您不要打电话的原因   从异步功能同步的任何事情,如果没有安全地执行,   或事先不知道这是一个非阻塞标准库   函数,例如os.path.join

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

我可以配置Pylint或Flake8来做到这一点吗?

我也不必介意它是否也抓住了上面的第一种情况(无害)。


更新:

在一个层面上,我意识到这是一个愚蠢的问题,正如米哈伊尔的回答所指出的那样。我们需要的是短绒应该检测到的“危险同步功能”的定义。

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

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

(我欢迎对此定义进行任何细化)

1 个答案:

答案 0 :(得分:1)

  

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

让我们澄清一些事情:本文中讨论的错误是当您在某个异步协程中调用任何长时间运行的同步函数时(它可以是I / O阻塞调用,也可以是具有很多计算的纯CPU函数)。这是一个错误,因为它将阻止整个事件循环,从而导致严重的性能降级(有关here的更多信息,包括答案下方的评论)。

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

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