(我使用的是Python 3.7)
import asyncio
result = 0
async def sub1():
global result
print('[*] sub1() start')
for i in range(1, 10000000):
result += i
print('[*] sub1() end')
async def sub2():
global result
print('[*] sub2() start')
for i in range(10000000, 20000000):
result += i
print('[*] sub2() end')
async def main():
await asyncio.gather(
asyncio.create_task(sub1()),
asyncio.create_task(sub2()),
)
asyncio.run(main())
当我执行上面的代码时,结果是
[*] sub1() start
[*] sub1() end
[*] sub2() start
[*] sub2() end
[Finished in 1.7s]
您知道sub2()
是在sub1()
完成之后开始的。
似乎无法并行工作。
我想将控制权交给sub2()
,直到sub1()
完成。
也许我必须将await
插入某处,但我不知道这是哪里。
问题
如何使用for循环并行执行两个函数?
谢谢。
答案 0 :(得分:1)
正如@KlausD在他的评论中指出的那样,仅添加async
标记并不能有效地使您的代码真正异步。 asyncio
在for-loops
中需要某种断点,以有效地知道何时在功能之间进行切换。这是一个利用同步功能并在循环的executor
(documentation here)中运行它们的可行解决方案:
import asyncio
result = 0
def sub1():
global result
print('[*] sub1() start')
for i in range(1, 10000000):
result += i
print('[*] sub1() end')
def sub2():
global result
print('[*] sub2() start')
for i in range(10000000, 20000000):
result += i
print('[*] sub2() end')
async def main(loop):
res = await asyncio.gather(
loop.run_in_executor(None, sub1),
loop.run_in_executor(None, sub2)
)
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
值得注意的是,编写异步代码必须记住要进行确保代码实际上异步运行的实践。实际上,Python中的本机for-loop
是一段同步代码,因此,在调用函数时,for循环将运行到完成,然后在线程中为下一个操作留出空间。
另一件事是,由于代码是简单的添加,因此实际上并没有通过异步运行代码节省任何时间。糟糕,您可能由于asyncio
操作必须在功能之间切换而浪费时间。异步功能非常适合需要在操作之间进行某种等待的大型处理(例如,进行各种服务器调用,其中一个必须等待服务器响应;读取多个文件,其中一个必须取决于硬盘驱动器的读取速度,在这种情况下,异步变得很有用,因为可以切换线程内的操作并确保在运行继续处理线程之前调用 all (从服务器中拉出;从硬盘驱动器中获取文件)的所有调用。请求或文件。