首页 > 解决方案 > 我应该在另一个进程/线程中调用我的异步函数吗?

问题描述

我正在用 pyppeteer 截取数千个网页。我偶然发现,在 2 个打开的终端中运行相同的脚本会使我得到的输出加倍。我通过打开最多 6 个终端并运行脚本对此进行了测试,我能够获得高达 6 倍的性能。

我正在考虑使用loop.run_in_executor在主程序的多个进程或线程中运行脚本。

这是正确的调用还是我在脚本中遇到了一些 IO/CPU 限制?

这就是我的想法。我不知道这是否是正确的做法。

import asyncio
import concurrent.futures

async def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

async def cpu_bound():
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    return sum(i * i for i in range(10 ** 7))

def wrap_blocking_io():
    return asyncio.run(blocking_io())

def wrap_cpu_bound():
    return asyncio.run(cpu_bound())

async def main():
    loop = asyncio.get_running_loop()
    # Options:
    # 1. Run in the default loop's executor:
    result = await loop.run_in_executor(
        None, wrap_blocking_io)
    print('default thread pool', result)
    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor(max_workers=6) as pool:
        result = await loop.run_in_executor(
            pool, wrap_blocking_io)
        print('custom thread pool', result)
    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor(max_workers=6) as pool:
        result = await loop.run_in_executor(
            pool, wrap_cpu_bound)
        print('custom process pool', result)

asyncio.run(main())

标签: pythonpython-3.xpython-asyncio

解决方案


我通过打开最多 6 个终端并运行脚本对此进行了测试,我能够获得高达 6 倍的性能。

由于pyppeteer已经是异步的,我认为您只是不并行运行多个浏览器,这就是为什么在运行多个进程时会增加输出。

要同时运行一些协程(“并行”),您通常使用类似asyncio.gather的东西。你的代码有吗?如果答案是否定的,请查看此示例- 这就是您应该运行多个作业的方式:

responses = await asyncio.gather(*tasks)

如果您已经使用asyncio.gather考虑提供最小的、可重现的示例,以便更容易理解发生了什么。


推荐阅读