我正在与Trio一起运行异步并发任务,该任务将在不同的网站上进行一些Web抓取。我希望能够选择与多少个并发工作人员一起工作。为此,我已经编写了这段代码
async def run_task():
s = trio.Session(connections=5)
Total_to_check = to_check() / int(module().workers)
line = 0
if int(Total_to_check) < 1:
Total_to_check = 1
module().workers = int(to_check())
for i in range(int(Total_to_check)):
try:
async with trio.open_nursery() as nursery:
for x in range(int(module().workers)):
nursery.start_soon(python_worker, self, s, x, line)
line += 1
except BlockingIOError as e:
print("[Fatal Error]", str(e))
continue
在此示例中,to_check()
等于提供了多少个URL来从中获取数据,而module().workers
等于我想要使用多少个并发工作器。
因此,假设我有30个网址,并且输入了10个并发任务,它将同时从10个网址中提取数据,并重复该过程3次。
现在,一切都很好,直到Total_to_check
(等于url数量除以worker数量)等于小数为止。
如果我说15个网址,并要求10个工作人员,那么此代码将仅检查10个网址。如果我有20个网址,但要求15个工人,则相同。
我可以做类似math.ceil(Total_to_check)的操作,但是它将开始尝试检查不存在的URL。
我该如何使其正常工作,因此,如果我有10个并发任务和15个url,它将并发检查前10个,然后并发检查最后5个而不跳过url? (或尝试检查太多)
谢谢!
答案 0 :(得分:2)
好吧,您将像这样使用CapacityLimiter:
async def python_worker(self, session, workers, line, limit):
async with limit:
...
然后,您可以简化run_task
:
async def run_task():
limit = trio.CapacityLimiter(10)
s = trio.Session(connections=5)
line = 0
async with trio.open_nursery() as nursery:
for x in range(int(to_check())):
nursery.start_soon(python_worker, self, s, x, line, limit)
line += 1
我相信BlockingIOError
也必须在python_worker
内移动,因为nursery.start_soon()
不会阻塞,这是__aexit__
的{{1}} >自动在nursery
块的末尾等待。