python asyncIO,如何挂起和恢复任务?
How python asyncIO, suspend & resume the task?
一种编程风格,其中任务在等待期间释放 CPU,以便其他任务可以使用它。
引入异步任务,
- 任务应该能够挂起和恢复
- 事件调度程序应该安排这些任务(准备就绪时)
写了事件 scheduler, but stuck in enabling an async task。假设任务受 IO 约束。在任务执行过程中,调度程序未获得 CPU 切片,因为任务是同步执行的。
python中的一个任务(bar
),当任务使用async
,await
[=31=时,变成异步任务(能够挂起和恢复) ]关键字 ayncio.onSomeIO
可等待,
async def bar():
await asyncio.onSomeIO()
问题:
asyncio
包如何使 bar
成为具有这些关键字的异步任务?每个任务是否在单独的线程上启动?
Does each task get launched on separate thread?
没有,asyncio 通常在单线程中运行。
How asyncio package enables bar, to be an async task, with these
keywords, under the hood?
当您将函数定义为 async
时,此函数成为生成器,允许使用 __next__()
方法执行它 "by steps"。 await
- 是 yield
(实际上 yield from
)执行流 returns 到管理所有协程执行的全局事件循环的点。
这个简单的示例展示了如何在不同生成器的执行流程之间切换:
def task(i):
yield 1
print('task {}: step 1'.format(i))
yield 2
print('task {}: step 2'.format(i))
tasks = [
task(1),
task(2),
task(3),
]
def execute_tasks(tasks):
i = 0
finished = []
while True:
# start executing tasks:
try:
tasks[i].__next__()
except StopIteration:
finished.append(i)
# check if any task unfinished:
if len(finished) == len(tasks):
return
# move to next unfinished task:
while True:
i += 1
if i > len(tasks) - 1:
i = 0
if not i in finished:
break
if __name__ == '__main__':
execute_tasks(tasks)
输出:
task 1: step 1
task 2: step 1
task 3: step 1
task 1: step 2
task 2: step 2
task 3: step 2
asyncio
当然要复杂得多,而且允许你做的更多。
可能是我在 PyCon 2015 视频中看到的关于如何使用生成器实现协程的最佳解释:David Beazley - Python Concurrency From the Ground Up: LIVE! (source code)。如果你要实施这个,你一定要看它。
但我建议您改用 asyncio
- 它已经为您准备好了,无需自己发明。
一种编程风格,其中任务在等待期间释放 CPU,以便其他任务可以使用它。
引入异步任务,
- 任务应该能够挂起和恢复
- 事件调度程序应该安排这些任务(准备就绪时)
写了事件 scheduler, but stuck in enabling an async task。假设任务受 IO 约束。在任务执行过程中,调度程序未获得 CPU 切片,因为任务是同步执行的。
python中的一个任务(bar
),当任务使用async
,await
[=31=时,变成异步任务(能够挂起和恢复) ]关键字 ayncio.onSomeIO
可等待,
async def bar():
await asyncio.onSomeIO()
问题:
asyncio
包如何使 bar
成为具有这些关键字的异步任务?每个任务是否在单独的线程上启动?
Does each task get launched on separate thread?
没有,asyncio 通常在单线程中运行。
How asyncio package enables bar, to be an async task, with these keywords, under the hood?
当您将函数定义为 async
时,此函数成为生成器,允许使用 __next__()
方法执行它 "by steps"。 await
- 是 yield
(实际上 yield from
)执行流 returns 到管理所有协程执行的全局事件循环的点。
这个简单的示例展示了如何在不同生成器的执行流程之间切换:
def task(i):
yield 1
print('task {}: step 1'.format(i))
yield 2
print('task {}: step 2'.format(i))
tasks = [
task(1),
task(2),
task(3),
]
def execute_tasks(tasks):
i = 0
finished = []
while True:
# start executing tasks:
try:
tasks[i].__next__()
except StopIteration:
finished.append(i)
# check if any task unfinished:
if len(finished) == len(tasks):
return
# move to next unfinished task:
while True:
i += 1
if i > len(tasks) - 1:
i = 0
if not i in finished:
break
if __name__ == '__main__':
execute_tasks(tasks)
输出:
task 1: step 1
task 2: step 1
task 3: step 1
task 1: step 2
task 2: step 2
task 3: step 2
asyncio
当然要复杂得多,而且允许你做的更多。
可能是我在 PyCon 2015 视频中看到的关于如何使用生成器实现协程的最佳解释:David Beazley - Python Concurrency From the Ground Up: LIVE! (source code)。如果你要实施这个,你一定要看它。
但我建议您改用 asyncio
- 它已经为您准备好了,无需自己发明。