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