如何在Python 3中正确使用异步等待与线程池

时间:2018-11-07 07:30:20

标签: python-3.x python-asyncio

我想达到与

相同的效果
# Code 1
from multiprocessing.pool import ThreadPool as Pool
from time import sleep, time

def square(a):
    print('start', a)
    sleep(a)
    print('end', a)
    return a * a

def main():
    p = Pool(2)
    queue = list(range(4))
    start = time()
    results = p.map(square, queue)
    print(results)
    print(time() - start)

if __name__ == "__main__":
    main()

具有类似异步功能

# Code 2
from multiprocessing.pool import ThreadPool as Pool
from time import sleep, time
import asyncio

async def square(a):
    print('start', a)
    sleep(a)  # await asyncio.sleep same effect
    print('end', a)
    return a * a

async def main():
    p = Pool(2)
    queue = list(range(4))
    start = time()
    results = p.map_async(square, queue)
    results = results.get()
    results = [await result for result in results]
    print(results)
    print(time() - start)

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()

当前代码1需要4秒钟,代码2需要6秒钟,这意味着它不是并行运行的。并行运行多个异步功能的正确和最干净的方法是什么?

最好与python 3.6兼容。谢谢!

1 个答案:

答案 0 :(得分:0)

df <- data.frame(size = round(rnorm(30, 39, 2)), pop = sample(c("kuopio", "tampere"), 30, replace = T), height = sample(c("short", "tall"), 30, replace = T)) tapply(df$size, INDEX = df[c(3, 2)], mean, na.rm=T) # df[c(3, 2)] refers to height and pop columns of df respectively pop height kuopio tampere short 39 39.57143 tall 41 39.22222 map_async()中的“异步”不同-如果使用async def方法馈送它,则它实际上不会运行,而是立即返回协程实例(请尝试在不使用async def的情况下调用此方法。然后,您await逐一await进入4个协程,这等于顺序执行,并以6秒结束。

请参见以下示例:

from time import time
import asyncio
from asyncio.locks import Semaphore

semaphore = Semaphore(2)


async def square(a):
    async with semaphore:
        print('start', a)
        await asyncio.sleep(a)
        print('end', a)
        return a * a


async def main():
    start = time()
    tasks = []
    for a in range(4):
        tasks.append(asyncio.ensure_future(square(a)))
    await asyncio.wait(tasks)
    print([t.result() for t in tasks])
    print(time() - start)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()

Semaphore的行为类似于ThreadPool,它只允许2个并发协程进入async with semaphore:块。