在 asyncio 异常后重新排队期货

Bla*_*ark 1 python asynchronous future task

我想弄清楚如何重新排队一些已超时的异步 DNS 请求(我正在使用 uvloop 和 aiodns 模块)。

这是我设置循环的代码:

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
resolver = aiodns.DNSResolver(loop=loop)
sem = asyncio.Semaphore(MAX_COUNT)
Run Code Online (Sandbox Code Playgroud)

此函数执行查找:

async def lookup(name):
    with (await sem):
        response = await resolver.query(name, 'A')
        return response
Run Code Online (Sandbox Code Playgroud)

我读入了一个包含名称的文件以查找和设置任务,包括处理结果的回调:

for n in names:
    host = '{}.{}'.format(n, domain)
    task = asyncio.ensure_future(lookup(host))
    tasks.append(task)
    task.add_done_callback(functools.partial(got_result, host))
Run Code Online (Sandbox Code Playgroud)

并启动查找队列。

print("Looking up {} subdomains...".format(len(names)))
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
Run Code Online (Sandbox Code Playgroud)

got_result回调中,我然后测试 future.exception() 并处理它,如果有,如果没有,则将结果打印到屏幕上。我可以接受一些例外情况(即找不到域名),但其他人喜欢超时,我想重新排队项目。是否有一种简单的方法可以将未来添加回循环以进行另一次尝试,还是我需要为此设置单独的功能并手动重新添加任务?

谢谢你的帮助。

sto*_*vfl 5

问题:...但其他人喜欢超时我想重新排队项目。

重新排队任务可能会导致死锁
保持任务,而不是重新排队任务,例如:

async def lookup(name):
    with (await sem):
        retries = 0
        while retries <= 5:
            try:
                response = await resolver.query(name, 'A')
                break
            except TimeoutError:
                retries += 1
                yield from asyncio.sleep(1)

        return response            
Run Code Online (Sandbox Code Playgroud)