[英]How to make a function that includes a for loop non-blocking?
我试图使下面的代码异步:
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:object int不能在'await'表达式中使用
我知道错误的发生是因为random.choice(l)
的结果不是一个等待的(协程),但我不知道如何解决这个问题,而不是在圈内运行。 我是否需要以某种方式将for循环重构为一个独立的couroutine?
是因为count函数缺少
await
语句吗?
简而言之,是的,您已正确识别问题。 要获得并行执行任务,您不仅需要指定async def
,还需要等待暂停执行的内容,从而将控制权返回给事件循环。 在asyncio中,这通常是一种阻止同步程序的调用,例如睡眠或从尚未准备好读取的套接字读取。
要强制临时暂停 ,可以在循环内添加await asyncio.sleep(0)
的count
。 在random.choice
之类的普通函数前添加await
random.choice
,因为await
需要一个实现等待接口的对象,并且在你的代码中random.choice
只返回一个整数。
您的代码调用同时运行long_task1
和long_task2
的gather
。 然后在每个函数中调用await on 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()
成为一项新任务:
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 ))
如果你有python 3.7,你也可以使用create_task
。
为了使asyncio正常工作,您不应该在事件循环中有任何cpu密集型任务(紧密的大循环)。 因为没有办法摆脱for循环。 如果你在循环中使用一个显式的asyncio.sleep
,你就会不必要地进出协程并减慢整个过程。 如果你的目标只是看看asyncio如何工作,那很好。
但在现实世界中,如果你有一个cpu密集型任务,你有两个选择
顾名思义,该库用于异步io。 async"io"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.