Python 如何使用run_in_executor right?

Python 如何使用run_in_executor right?,python,python-asyncio,Python,Python Asyncio,我尝试使用run\u in\u executor,并提出了一些问题。下面是代码(基本上是从文档复制过来的) 案例1:run\u in\u executor其中executor为None: async\u任务与cpu绑定的执行同时执行 在其他情况下,异步任务将在cpu绑定完成后执行。 我认为当我们使用ProcessPoolExecutor任务时,不应该阻塞循环。我错在哪里 在其他情况下,异步任务将在cpu绑定完成后执行。我认为当我们使用ProcessPoolExecutor任务时,不应该阻塞循环。

我尝试使用
run\u in\u executor
,并提出了一些问题。下面是代码(基本上是从文档复制过来的)

案例1:
run\u in\u executor
其中
executor
None
async\u任务
cpu绑定
的执行同时执行

在其他情况下,
异步任务
将在
cpu绑定
完成后执行。 我认为当我们使用
ProcessPoolExecutor
任务时,不应该阻塞循环。我错在哪里

在其他情况下,
异步任务
将在
cpu绑定
完成后执行。我认为当我们使用
ProcessPoolExecutor
任务时,不应该阻塞循环。我错在哪里

问题在于
with XXXPoolExecutor()
会关闭
with
块末尾的池。池关闭等待挂起的任务完成,这会阻止事件循环,并且与asyncio不兼容。因为您的第一个变体不涉及
with
语句,所以它没有这个问题

解决方案只是删除
with
语句并创建一次池(例如在顶层或
main()
),然后在函数中使用它。如果愿意,可以在
asyncio.run()
完成后通过调用
pool.shutdown()
显式关闭池


还请注意,您从不等待
循环返回的期货。在执行器中运行。这是一个错误,asyncio可能会警告您;您可能应该收集列表中的返回值,并使用类似于
results=await asyncio.gather(*tasks)
的方法等待它们。这不仅可以收集结果,还可以确保线程外函数中发生的异常正确地传播到代码中,而不是被删除。

我使用asyncio在循环中运行requests.get()。不等待loop.run_in_executor的结果可以吗?@r2b2这个答案认为您应该在某个地方等待它们,所以如果没有其他异常,您可以收集异常。不等待可能不是致命缺陷,请查看是否从asyncio收到任何警告。此外,如果您真的不关心结果或异常,那么首先可能不需要
run\u in\u executor()
,您可以调用
executor.submit()
run\u in_executor()
的要点是将
并发的.futures.Future
(由
executor.submit
返回)转换为可等待的
asyncio.Future
。如果不需要该功能,可以直接使用executor。
import asyncio
import concurrent.futures


def cpu_bound(val):
    # CPU-bound operations will block the event loop:
    # in general it is preferable to run them in a
    # process pool.
    print(f'Start task: {val}')
    sum(i * i for i in range(10 ** 7))
    print(f'End task: {val}')


async def async_task(val):
    print(f'Start async task: {val}')
    while True:
        print(f'Tick: {val}')
        await asyncio.sleep(1)


async def main():
    loop = asyncio.get_running_loop()

    ## Options:

    for i in range(5):
        loop.create_task(async_task(i))

    # 1. Run in the default loop's executor:
    # for i in range(10):
    #     loop.run_in_executor(
    #         None, cpu_bound, i)
    # print('default thread pool')

    # 2. Run in a custom thread pool:
    # with concurrent.futures.ThreadPoolExecutor(max_workers=10) as pool:
    #     for i in range(10):
    #         loop.run_in_executor(
    #             pool, cpu_bound, i)
    #     print('custom thread pool')

    # 3. Run in a custom process pool:
    with concurrent.futures.ProcessPoolExecutor(max_workers = 10) as pool:
        for i in range(10):
            loop.run_in_executor(
                pool, cpu_bound, i)
        print('custom process pool')

    while True:
        await asyncio.sleep(1)


asyncio.run(main())