Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用asyncio添加连接超时?_Python_Python 3.x_Asynchronous_Timeout_Python Asyncio - Fatal编程技术网

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

Python 如何使用asyncio添加连接超时?,python,python-3.x,asynchronous,timeout,python-asyncio,Python,Python 3.x,Asynchronous,Timeout,Python Asyncio,我想连接到许多不同的网站列表非常快。 我正在使用asyncio以异步方式完成这项工作,现在我想 如果连接需要太长时间才能响应,请为其添加超时,以确定何时应忽略连接 我如何实现这一点 import ssl import asyncio from contextlib import suppress from concurrent.futures import ThreadPoolExecutor import time @asyncio.coroutine def run(): whi

我想连接到许多不同的网站列表非常快。 我正在使用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)

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

您可以将调用包装到
open\u 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\u连接
corroutine。如果您不想取消它(虽然我认为您确实希望在这种情况下取消它),那么您必须将调用打包。

您忘记了从
调用
q.put(None)
内部
加载
,因此此代码不会按当前编写的方式工作。您不需要读写器。您可以使用
asyncio.create\u connection
Protocol
创建不起任何作用的连接(一旦建立网络连接就会关闭)。这里是(它可能有点过时,例如,它没有使用一些方便的函数,例如
asyncio.wait_for()
)。它使用一个线程,并打开最多
限制
ssl连接。但这也将使其成为阻塞调用否?就像在正常循环中一个接一个地打开连接一样。@ali否,因为对
run
方法的所有调用都包装在
asyncio.async
调用中,这意味着它们都同时运行。如果连接超时需要在另一个协程中,请参阅[asyncio force timeout]中有关堆叠
asyncio的内容。确保\u(asyncio.wait_for(create_connection())
我敢肯定,由于wait_for doc中提到的更改,3.7版中更改了
:当aw由于超时而取消时,等待aw被取消。之前,它会立即引发asyncio.TimeoutError。