5

我有一个应用程序每隔几分钟就轮询一堆服务器。为此,它为每个服务器生成一个线程来轮询(15 个服务器)并将数据写回一个对象:

import requests

class ServerResults(object):
    def __init__(self):
        self.results = []

    def add_server(some_argument):
        self.results.append(some_argument)

servers = ['1.1.1.1', '1.1.1.2']
results = ServerResults()

for s in servers:
    t = CallThreads(poll_server, s, results)
    t.daemon = True
    t.start()

def poll_server(server, results):
    response = requests.get(server, timeout=10)
    results.add_server(response.status_code);

该类CallThreads是调用函数的辅助函数(在本例poll_server()中带有参数(在本例中为sand ),您可以在我的Python 实用程序函数results的 Github 存储库中查看源代码。大多数情况下这工作正常,但有时线程间歇性挂起。我不知道为什么,因为我在 GET 请求上使用了超时。无论如何,如果线程挂起,那么挂起的线程会在几个小时或几天内建立起来,然后 Python 崩溃:

  File "/usr/lib/python2.7/threading.py", line 495, in start
    _start_new_thread(self.__bootstrap, ())
thread.error: can't start new thread

Exception in thread Thread-575 (most likely raised during interpreter shutdown)
Exception in thread Thread-1671 (most likely raised during interpreter shutdown)
Exception in thread Thread-831 (most likely raised during interpreter shutdown)

我该如何处理?似乎没有办法杀死 Python 阻塞 线程 。这个应用程序需要在树莓派上运行,所以大型库(如twisted)不适合,实际上我也需要摆脱requests库!

4

1 回答 1

4

据我所知,一种可能的情况是,当一个给定服务器的线程“挂起”时,它将“永远”留在那里。下次查询服务器时,会产生另一个线程 ( _start_new_thread),直到 Python 崩溃。

可能不是您的(主要)问题,但您应该:

  • 使用线程池 - 这不会像一次又一次地产生新线程那样对系统的有限资源造成压力。
  • 检查您是否使用“线程兼容”机制来处理对results. 也许 a semaphoreormutex锁定代码的原子部分。可能更好的是专用数据结构,例如queue.

关于“挂起”本身- 请注意“打开 URL”(urlopen )时的超时参数与建立连接的超时有关。不用于下载实际数据:

可选的 timeout 参数以秒为单位指定连接尝试等阻塞操作的超时时间(如果未指定,将使用全局默认超时设置)。这实际上只适用于 HTTP、HTTPS 和 FTP 连接。

于 2013-07-30T09:44:27.113 回答