Python 使用ThreadPoolExecutor强制线程超时

Python 使用ThreadPoolExecutor强制线程超时,python,multithreading,timeout,threadpool,Python,Multithreading,Timeout,Threadpool,我正在升级我的代码以使用ThreadPoolExecuter,并希望能够超时任何需要几秒钟以上处理的线程。是否可以对作为线程池一部分的线程强制超时?下面是我正在使用的代码 with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor: future_tasks = {executor.submit(self.crawl_task, url): url for url in self.resul

我正在升级我的代码以使用ThreadPoolExecuter,并希望能够超时任何需要几秒钟以上处理的线程。是否可以对作为线程池一部分的线程强制超时?下面是我正在使用的代码

    with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
        future_tasks = {executor.submit(self.crawl_task, url): url for url in self.results.keys()}

        for future in concurrent.futures.as_completed(future_tasks):
            url = future_tasks[future]
            try:
                result = future.result()
                self.results[result[0]] = result[1]
            except Exception as e:
                print('%r generated an exception: %s' % (url, e))
我能够使线程超时的唯一方法是更改

for future in concurrent.futures.as_completed(future_tasks):

但是,这将破坏整个循环,我无法知道哪个线程超时,以及哪些数据导致超时

Traceback (most recent call last):
  File "test.py", line 75, in <module>
    request = Requests(data)
  File "test.py", line 22, in __init__
    for future in concurrent.futures.as_completed(future_tasks, timeout=1):
  File "/source/homebrew/Cellar/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4/    lib/python3.4/concurrent/futures/_base.py", line 213, in as_completed
    len(pending), len(fs)))
concurrent.futures._base.TimeoutError: 17 (of 17) futures unfinished
回溯(最近一次呼叫最后一次):
文件“test.py”,第75行,在
请求=请求(数据)
文件“test.py”,第22行,在_init中__
对于concurrent.futures.as_中的future(future_任务,超时=1):
文件“/source/homebrew/ceral/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/concurrent/futures/_base.py”,第213行,已完成
len(待定),len(fs)))
并发.futures.\u base.timeouter错误:17个(共17个)futures未完成

一种方法是在self.crawl\u任务开始执行时将url记录到文件中。在线程任务完成之前,它可以附加一个字符串“DONE”,可能还有一个时间戳


此外,您还需要处理TimeoutError异常,以避免执行中断。如果有超时,您可以查看其中没有“DONE”字符串的文件日志

在异常中包装整个for futures循环仍然允许其他线程处理结果。使用两个单独的字典,您可以看到哪些线程由于超时而停止

with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
    future_tasks = {executor.submit(self.crawl_task, url): url for url in self.requests.keys()}

    try:
        for future in concurrent.futures.as_completed(future_tasks, timeout=10):
            result = future.result()
            self.responses[result[0]] = result[1]
    except Exception as e:
        print(e)

timeout = [url for url in self.requests.keys() if url not in self.responses.keys()]

print('URL Threads timed out: ', timeout)

我必须指出,这与传统智慧背道而驰。通常,如果在异常中包装整个for循环,则循环中异常之后的任何内容都不应处理,但未来的魔力似乎允许循环中的所有内容(超时的线程除外)处理。

这将导致整个循环中断,并将丢失其他几个未超时线程的数据。分析日志文件不是管理线程状态的理想方法。您可以在try块中嵌入“for future in concurrent.futures.as_completed(future_tasks):”并忽略异常。您可以通过简单地标记此条件来忽略,以便查看日志。这将导致所有线程超时。如何在不超时整个线程池的情况下超时单个线程?result()中似乎提供了超时支持。例如,result(timeout=None),我看到另一个stackoverflow帖子发布了它,并尝试了它。它实际上不会导致超时,也找不到任何关于它的文档。谢谢,这解决了我的问题。然而,我仍然有点困惑这个魔术,并没有找到任何关于它的文件。
with concurrent.futures.ThreadPoolExecutor(max_workers=16) as executor:
    future_tasks = {executor.submit(self.crawl_task, url): url for url in self.requests.keys()}

    try:
        for future in concurrent.futures.as_completed(future_tasks, timeout=10):
            result = future.result()
            self.responses[result[0]] = result[1]
    except Exception as e:
        print(e)

timeout = [url for url in self.requests.keys() if url not in self.responses.keys()]

print('URL Threads timed out: ', timeout)