是什么阻止我的异步代码运行异步?

时间:2019-07-23 15:46:34

标签: python python-3.x asynchronous

我试图离开线程并开始使用异步。我试图写一些简单的东西,以便对异步更加适应。由于某种原因,我的异步代码未执行异步操作。

我在线程中重写了相同的代码,与异步代码不同,它可以快速并发地工作。

正常代码

import time 
import random

def display(x: int) -> None:
    time.sleep(random.randint(1, 8))
    print(x)

def main():
    for i in range(10):
        display(i) 

if __name__ == '__main__':
    main()   

输出

0
1
2
3
4
5
6
7
8
9

异步代码

import time 
import random
import asyncio

async def display(x: int) -> None:
    await asyncio.sleep(random.randint(1, 8))
    print(x)

async def main():
    for i in range(10):
        await display(i)

if __name__ == '__main__':
    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(main())
    event_loop.close()

输出

0
1
2
3
4
5
6
7
8
9

线程代码

import time 
import random 
import threading 

def display(x: int) -> None:
    time.sleep(random.randint(1, 8))
    print(x)

def main():
    threads = []

    for i in range(10):
        t = threading.Thread(target=display, args=[i])
        threads.append(t)
        t.start()

    for t in threads:
        t.join()


if __name__ == '__main__':
    main()

输出

5
9
3
0
4
2
1
8
6
7

1 个答案:

答案 0 :(得分:1)

await display(i)使用参数display运行i,该参数返回 awaitable 。然后,您立即使用await等待呼叫,从而阻止该呼叫。

如果要一起计划所有计划,然后在最后等待,则需要将等待项收集到列表中,然后立即等待所有计划。

import time
import random
import asyncio

async def display(x: int) -> None:
    await asyncio.sleep(random.randint(1, 8)/10)
    print(x)

async def main():
    awaitables = []
    for i in range(10):
        awaitables.append(display(i))
    await asyncio.wait(awaitables)

if __name__ == '__main__':
    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(main())
    event_loop.close()

是的,因为否则肯定会指出来,您也可以将其写在列表理解中:

async def main():
    await asyncio.wait([display(i) for i in range(10)])

更多说明:

我确定您知道,但是无论如何我都认为很重要。该代码运行异步,但不是 parallel 。使用asyncthreading.Thread运行多个计算繁重的函数仍然只能在一个CPU内核上运行它们,而没有任何加速。 Python解释器是单线程的。