我正在尝试使以下代码异步:
import asyncio
import random
async def count():
l = []
for i in range(10000000):
l.append(i)
return random.choice(l)
async def long_task1():
print('Starting task 1...')
task_output = await count()
print('Task 1 output is {}'.format(task_output ))
async def long_task2():
print('Starting task 2...')
task_output = await count()
print('Task 2 output is {}'.format(task_output ))
async def main():
await asyncio.gather(long_task1(), long_task2())
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
当前它将同步工作。
是因为count
函数缺少await
语句吗?
我尝试过对该函数进行重新设计以使其包含await
:
async def count():
l = []
for i in range(10000000):
l.append(i)
choice = await random.choice(l)
return choice
,它将异步启动(Starting task 1...
和Starting task 2...
都将被依次打印),但是随后出现错误:
TypeError:对象int不能在“等待”表达式中使用
我知道发生此错误是因为random.choice(l)
的结果不是可以等待的(协程),但是我不知道如何解决这个问题而不需要盘旋。我是否需要以某种方式将for循环重构为一个couroutine?
答案 0 :(得分:3)
是因为count函数缺少
await
语句吗?
简而言之,是的,您已经正确识别了问题。要并行执行任务,不仅需要指定async def
,而且还需要等待一些暂停执行的操作,从而将控制权返回到事件循环。在异步中,这通常是一种阻塞同步程序的调用,例如睡眠或尚未准备好读取的套接字读取。
要强制使用temporary suspension,可以在await asyncio.sleep(0)
的循环内添加count
。在await
之类的普通函数之前添加random.choice
无效,因为await
需要一个实现等待接口的对象,并且在代码random.choice
中仅返回整数。
答案 1 :(得分:1)
您的代码将调用同时运行gather
和long_task1
的{{1}}。然后,您在每个函数中的long_task2
上调用await。但这将在该子例程上count
完成。因此,整个子例程仍将在下一个子例程开始之前完成。您需要一个函数来暂停整个任务。我创建了两种方法来避免这种情况。两者都涉及创建新任务。
创建一个新的子例程:
await
您还可以使async def count():
l = []
await asyncio.wait_for(loopProcess(l), timeout=1000000.0)
return random.choice(l)
async def loopProcess(l):
for i in range(10000000):
l.append(i)
的功能与原始代码相同,并像这样更改count
以使long_task(1/2)
成为新任务:
count()
如果您使用python 3.7,也可以使用async def long_task1():
print('Starting task 1...')
task_output = await asyncio.shield(count())
print('Task 1 output is {}'.format(task_output ))
async def long_task2():
print('Starting task 2...')
task_output = await asyncio.shield(count())
print('Task 2 output is {}'.format(task_output ))
。
答案 2 :(得分:1)
为使asyncio正常工作,在事件循环中不应执行任何占用大量CPU资源的任务(对于循环来说是紧紧的任务)。由于没有办法摆脱for循环。如果在循环中使用显式asyncio.sleep
,则只是不必要地进入和退出协程,从而使整个过程变慢。如果您的目标只是看异步如何工作,那很好。
但是在现实世界中,如果您要执行大量的CPU任务,则有两种选择
顾名思义,该库用于异步io。 async"io"