首页 文章

Python asyncio任务排序

提问于
浏览
1

我有一个问题,关于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() 重新放回队列的末尾 .

我可以得到一个阿门吗?

1 回答

  • 1

    目前,您的示例不包含任何阻塞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()
    

    如您所见,协同程序根据需要进行安排,而不是按顺序安排 .

相关问题