Python asyncio 任务排序

标签 python queue python-asyncio event-loop

我对 python 的 asyncio 模块中的事件循环如何管理未完成的任务有疑问。考虑以下代码:

import asyncio

@asyncio.coroutine
def a():
   for i in range(0, 3):
      print('a.' + str(i))
      yield


@asyncio.coroutine
def b():
   for i in range(0, 3):
      print('b.' + str(i))
      yield


@asyncio.coroutine
def c():
   for i in range(0, 3):
      print('c.' + str(i))
      yield


tasks = [
   asyncio.Task(a()),
   asyncio.Task(b()),
   asyncio.Task(c()),
]

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([t1, t2, t3]))

运行它会打印:

a.0
b.0
c.0
a.1
b.1
c.1
a.2
b.2
c.2

请注意,它总是先打印出“a”,然后是“b”,然后是“c”。我猜想无论每个协程经过多少次迭代,它都将始终按该顺序打印。所以你永远不会看到类似的东西

b.100
c.100
a.100

来自 node.js 背景,这告诉我这里的事件循环在内部维护一个队列,它用来决定接下来要运行哪个任务。它最初将 a() 放在队列的前面,然后是 b(),然后是 c(),因为这是任务的顺序在传递给 asyncio.wait() 的列表中。然后,每当它遇到 yield 语句时,它就会将该任务放在队列的末尾。我想在一个更现实的例子中,假设你正在执行异步 http 请求,它会在 http 响应返回后将 a() 放回队列的末尾。

我可以得到一个阿门吗?

最佳答案

目前您的示例不包含任何阻塞 I/O 代码。试试这个来模拟一些任务:

import asyncio


@asyncio.coroutine
def coro(tag, delay):
    for i in range(1, 8):
        print(tag, i)
        yield from asyncio.sleep(delay)


loop = asyncio.get_event_loop()

print("---- await 0 seconds :-) --- ")
tasks = [
    asyncio.Task(coro("A", 0)),
    asyncio.Task(coro("B", 0)),
    asyncio.Task(coro("C", 0)),
]

loop.run_until_complete(asyncio.wait(tasks))

print("---- simulate some blocking I/O --- ")
tasks = [
    asyncio.Task(coro("A", 0.1)),
    asyncio.Task(coro("B", 0.3)),
    asyncio.Task(coro("C", 0.5)),
]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()

如您所见,协程是按需安排的,而不是按顺序安排的。

关于Python asyncio 任务排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41785617/

相关文章:

python - 如何使用 asyncio 复杂地管理 shell 进程?

python - 并行读取文件并参数化类参数

python - 数组 reshape 未正确映射到 numpy 网格

c - 使用SJF(SPN)算法推送队列

python - django中的url可以传入空字符串吗?

c - 为什么我要覆盖我的结构?实现队列,但是行不通

algorithm - 带约束的二维遍历算法

python - 如何在使用 Python 3 和 asyncio 实时写入文件时读取文件,例如 "tail -f"

python - 在 Jython 中使用 OrderedDict

python - 如何直接从 cmd 运行 .py 脚本?