我基于https://docs.python.org/3/library/concurrent.futures.html#id1中的示例。

我更新了以下内容:
data = future.result()
对此:
data = future.result(timeout=0.1)

concurrent.futures.Future.result的文档指出:


  如果通话未在超时秒内完成,则将引发TimeoutError。超时可以是int或float


(我知道请求的超时时间为60,但是在我的实际代码中,我正在执行不使用urllib请求的其他操作)

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    conn = urllib.request.urlopen(url, timeout=timeout)
    return conn.readall()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            # The below timeout isn't raising the TimeoutError.
            data = future.result(timeout=0.01)
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))


如果我在对TimeoutError的调用中将as_completed设置为引发,但我需要基于每个Future设置超时,而不是将它们作为一个整体来设置。



更新资料

感谢@jme,它适用于单个Future,但不适用于使用下面的倍数。我是否需要在函数开头使用yield来允许建立futures字典?在文档中,听起来好像不应该阻止对submit的调用。

import concurrent.futures
import time
import sys

def wait():
    time.sleep(5)
    return 42

with concurrent.futures.ThreadPoolExecutor(4) as executor:
    waits = [wait, wait]
    futures = {executor.submit(w): w for w in waits}
    for future in concurrent.futures.as_completed(futures):
        try:
            future.result(timeout=1)
        except concurrent.futures.TimeoutError:
            print("Too long!")
            sys.stdout.flush()

print(future.result())

最佳答案

问题似乎与调用concurrent.futures.as_completed()有关。

如果仅用for循环替换它,一切似乎都可以正常工作:

for wait, future in [(w, executor.submit(w)) for w in waits]:
    ...


我误解了as_completed的文档,其中指出:


  在完成时(完成或取消)的收益期货...


as_completed将处理超时,但整体而言,而不是将来的超时。

10-06 11:26