如何使用asyncio添加连接超时?

2024-03-29 14:38:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我想很快连接到很多不同网站的列表。 我使用asyncio以异步方式执行此操作,现在希望 如果连接需要太长时间才能响应,请添加应忽略连接的超时时间。

我该如何实现?

import ssl
import asyncio
from contextlib import suppress
from concurrent.futures import ThreadPoolExecutor
import time


@asyncio.coroutine
def run():
    while True:
        host = yield from q.get()
        if not host:
            break

        with suppress(ssl.CertificateError):
            reader, writer = yield from asyncio.open_connection(host[1], 443, ssl=True) #timout option?
            reader.close()
            writer.close()


@asyncio.coroutine
def load_q():
    # only 3 entries for debugging reasons
    for host in [[1, 'python.org'], [2, 'qq.com'], [3, 'google.com']]:
        yield from q.put(host)
    for _ in range(NUM):
        q.put(None)


if __name__ == "__main__":
    NUM = 1000
    q = asyncio.Queue()

    loop = asyncio.get_event_loop()
    loop.set_default_executor(ThreadPoolExecutor(NUM))

    start = time.time()
    coros = [asyncio.async(run()) for i in range(NUM)]
    loop.run_until_complete(load_q())
    loop.run_until_complete(asyncio.wait(coros))
    end = time.time()
    print(end-start)

(旁注:有人知道如何优化它吗?)


Tags: runinfromimportloopasynciohostssl
1条回答
网友
1楼 · 发布于 2024-03-29 14:38:25

您可以将对open_connection的调用包装在^{}中,这允许您指定超时:

    with suppress(ssl.CertificateError):
        fut = asyncio.open_connection(host[1], 443, ssl=True)
        try:
            # Wait for 3 seconds, then raise TimeoutError
            reader, writer = yield from asyncio.wait_for(fut, timeout=3)
        except asyncio.TimeoutError:
            print("Timeout, skipping {}".format(host[1]))
            continue

请注意,当引发TimeoutError时,也会取消open_connection协程。如果您不想取消它(尽管我认为您希望在本例中取消它),您已经将调用包装成^{}

相关问题 更多 >