如何同时 运行 `n` python 协程?
How do I run `n` python coroutines concurrently?
我已经用 async def
创建了一个 async
python 协程,我想 运行 它遍历列表中的每个元素。
但是,协程启动一个单独的进程,我的电脑资源有限,所以我想同时只运行 n
个这些协程。一个完成后,我想开始另一个。
我仍在学习 asyncio
,但我不知道如何在此框架内执行此操作。
我知道我可以 运行 n
作业同时使用像这样的东西:
commands = asyncio.gather(*[run_command(f) for f in islice(my_large_list,n)])
# Run the commands
results = loop.run_until_complete(commands)
但是,我不知道如何在每个作业完成时替换它。
一种选择是使用 asyncio.Semaphore
:
import asyncio
import random
s = asyncio.Semaphore(5)
async def my_coroutine(i):
async with s:
print("start", i)
await asyncio.sleep(random.uniform(1, 3))
print("end", i)
loop = asyncio.get_event_loop()
tasks = [my_coroutine(i + 1) for i in range(50)]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
Update: concurrent.futures
可能比 asycnio 更容易解决你的问题,因为执行者有一个非常简单的 max_workers 参数:
import concurrent.futures
import time
import random
def my_routine(i):
print("start", i)
# Here you can use subprocess.* for anything, instead we will sleep:
time.sleep(random.uniform(1, 3))
print("end", i)
return "i={}".format(i)
with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
jobs = {executor.submit(my_routine, i + 1) for i in range(50)}
for fut in concurrent.futures.as_completed(jobs):
print(fut.result())
print('done')
我已经用 async def
创建了一个 async
python 协程,我想 运行 它遍历列表中的每个元素。
但是,协程启动一个单独的进程,我的电脑资源有限,所以我想同时只运行 n
个这些协程。一个完成后,我想开始另一个。
我仍在学习 asyncio
,但我不知道如何在此框架内执行此操作。
我知道我可以 运行 n
作业同时使用像这样的东西:
commands = asyncio.gather(*[run_command(f) for f in islice(my_large_list,n)])
# Run the commands
results = loop.run_until_complete(commands)
但是,我不知道如何在每个作业完成时替换它。
一种选择是使用 asyncio.Semaphore
:
import asyncio
import random
s = asyncio.Semaphore(5)
async def my_coroutine(i):
async with s:
print("start", i)
await asyncio.sleep(random.uniform(1, 3))
print("end", i)
loop = asyncio.get_event_loop()
tasks = [my_coroutine(i + 1) for i in range(50)]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
Update: concurrent.futures
可能比 asycnio 更容易解决你的问题,因为执行者有一个非常简单的 max_workers 参数:
import concurrent.futures
import time
import random
def my_routine(i):
print("start", i)
# Here you can use subprocess.* for anything, instead we will sleep:
time.sleep(random.uniform(1, 3))
print("end", i)
return "i={}".format(i)
with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
jobs = {executor.submit(my_routine, i + 1) for i in range(50)}
for fut in concurrent.futures.as_completed(jobs):
print(fut.result())
print('done')