d51*_*512 8 python queue event-loop python-asyncio
我有一个关于 pythonasyncio模块中的事件循环如何管理未完成任务的问题。考虑以下代码:
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]))
Run Code Online (Sandbox Code Playgroud)
运行这将打印:
a.0
b.0
c.0
a.1
b.1
c.1
a.2
b.2
c.2
Run Code Online (Sandbox Code Playgroud)
请注意,它总是打印出 'a' 然后是 'b' 然后是 'c'。我猜无论每个协程经过多少次迭代,它都将始终按该顺序打印。所以你永远不会看到类似的东西
b.100
c.100
a.100
Run Code Online (Sandbox Code Playgroud)
来自 node.js 背景,这告诉我这里的事件循环在内部维护一个队列,它用来决定接下来运行哪个任务。它最初放在a()队列的前面,然后是b(),然后c()因为这是传递给 的列表中任务的顺序asyncio.wait()。然后每当它遇到一个 yield 语句时,它就会将该任务放在队列的末尾。我想在一个更现实的例子中,假设你在做一个异步 http 请求,它会放a()在 http 响应回来后放回队列的末尾。
我可以得到一个阿门吗?
目前您的示例不包含任何阻塞 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()
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,协程是根据需要而不是按顺序来安排的。
| 归档时间: |
|
| 查看次数: |
3806 次 |
| 最近记录: |