简体   繁体   English

Python asyncio非阻塞循环

[英]Python asyncio non blocking for loop

(I used Python 3.7) (我使用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())

When I execute above code, it's result is 当我执行以上代码时,结果是

[*] sub1() start
[*] sub1() end
[*] sub2() start
[*] sub2() end
[Finished in 1.7s]

You know that, sub2() is started after sub1() finished. 您知道sub2()sub1()完成之后启动。

It seems doesn't work in parallel. 似乎无法并行工作。

I want to give control over to sub2() until sub1() finished. 我想将控制权交给sub2()直到sub1()完成。

Maybe I have to insert await to somewhere, but I don't know where is the point. 也许我必须将await插入某个地方,但我不知道重点在哪里。

Question

How can I execute both functions like parallel using for loop? 如何执行两个函数(如并行使用for循环)?

Thanks. 谢谢。

As @KlausD pointed out in his comment simply adding the async tag does not effectively make your code truly asynchronous. 正如@KlausD在他的评论中指出的那样,仅仅添加async标签并不能有效地使您的代码真正异步。 asyncio requires some sort of break-point within the for-loops to effectively know when to switch between functions. asynciofor-loops需要某种断点for-loops以有效地知道何时在功能之间进行切换。 Here is a possible solution utilizing synchronous functions and running them inside the loop's executor ( documentation here ): 这是一个利用同步功能并在循环的executor运行它们的可能解决方案( 此处的文档 ):

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))

It is worth noting that to write asynchronous code one must remember to engage in practices that ensure the code actually runs asynchronously. 值得注意的是,编写异步代码必须记住要进行确保代码实际上异步运行的实践。 A native for-loop in Python is in fact a synchronous piece of code, and therefore when your functions are called, the for-loop is run until completion before making space in the thread for the next operation. 实际上,Python中的本机for-loop实际上是一段同步代码,因此,在调用函数时,for循环将运行到完成,然后在线程中为下一个操作留出空间。

Another thing is the fact that since your code is simple additions, you aren't actually saving any time by running it asynchronously. 另一件事是这样的事实,因为您的代码是简单的添加,您实际上并没有通过异步运行它节省任何时间。 Hell, you might be losing time due to asyncio operations having to switch between functions. asyncio ,您可能由于asyncio操作不得不在功能之间切换而浪费时间。 Async functionalities are good for large processing that requires some sort of waiting between operations (ie doing various server calls, where one has to wait for servers to respond; reading in multiple files, where one has to be dependent on the hard drive reading speed, etc.) In these cases, async becomes useful since one can switch operations within the thread and ensure that all the calls (pull from server; get file from harddrive) are run before bothering moving on to processing the requests or the files. 异步功能非常适合需要在操作之间进行某种等待的大型处理(例如,进行各种服务器调用,其中一个必须等​​待服务器响应;读取多个文件,其中一个必须取决于硬盘驱动器的读取速度,在这些情况下,异步变得很有用,因为可以在线程内切换操作并确保所有调用(从服务器中拉出;从硬盘驱动器中获取文件)在麻烦继续处理请求或文件之前都已运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM