asyncio的事件循环使用哪种调度算法?

时间:2019-12-13 03:48:57

标签: python python-asyncio scheduling

我浏览了所有文档,但找不到它。

假设完成了多个await调用,并且它们的协程都准备好恢复了,asyncio的事件循环使用什么算法来决定恢复哪个协程?

1 个答案:

答案 0 :(得分:1)

1) Documentation向我们展示了事件循环以run_forever / run_until_complete开始。我们需要找到函数的源代码,看看接下来会发生什么。

2)(我知道)最快的方法是在github上搜索相关名称。转到github.com/python/cpython,使用左上角的搜索表单:

enter image description here

Github将向您显示项目中的所有事件。确保您搜索代码:

enter image description here

3),我们需要实现,发现其中两个:one inside ProactorEventLoop,因为它部分地重新实现了父事件循环,所以没有什么有趣的事情发生;和one inside BaseEventLoop,这似乎是我们要搜索的内容。

4)让我们检查一下代码。很快我们就会看到,一切都在_run_once循环内调用while True了:

try:
    events._set_running_loop(self)
    while True:
        self._run_once()
        if self._stopping:
            break

5)让我们go to _run_once(我们可以在页面上搜索def _run_once)。这是恢复安排好的事情的地方。您会在源代码中看到两个有趣的地方:

  • Lineevent_list = self._selector.select(timeout)-异步睡眠的地方,直到套接字上的活动为止。您可以进一步阅读documentation来研究这种机制。但是这个地方不会自行恢复协程。
  • Line,其中显示:This is the only place where callbacks are actually *called*. All other places just add them to ready.

正是我们搜索的内容。您可以在此处(通常在_run_once函数内部)阅读源代码,以了解如何执行回调以及如何将其添加到self._ready中以执行。回调包括添加了directly的回调和asyncio在内部用于恢复协程的回调。

您还可以重新实现事件循环以进行播放。看一下code here,其中包含事件循环重新实现的示例。


一些注意事项:

  • 除非文档中另有说明,否则具体算法是实现的详细信息,并且可以在asyncio版本之间进行更改。您不应该依赖它。
  • 不同的事件循环可以实现不同的算法。尽管所有异步循环似乎都使用BaseEventLoop中的一个,但其他事件循环(例如自定义uvloop)可能会有所不同。
  • 通常可以找到我在PyCharm中使用ctrl+click的东西的源代码。它比在github上搜索更快,更方便,但是由于某些原因不能与asyncio一起使用。