Python Trio设置了十进制工人数

时间:2019-06-20 22:36:15

标签: python python-3.x asynchronous concurrency python-trio

我正在与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? (或尝试检查太多)

谢谢!

1 个答案:

答案 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块的末尾等待。