Python崩溃的输出原因

时间:2013-07-30 09:06:56

标签: python multithreading

我有一个应用程序,每隔几分钟轮询一堆服务器。为此,它为每个服务器生成一个线程进行轮询(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()带有参数(在本例中为sresults),你可以看到源于我的Python utility functions的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)

我该如何处理?似乎无法kill a blocking thread in Python。这个应用程序需要在Raspberry Pi上运行,因此twisted等大型库不适合,实际上我也需要摆脱requests库!

1 个答案:

答案 0 :(得分:4)

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

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

  • 使用线程池 - 这不会对系统的有限资源施加压力,就像一次又一次地生成 new 线程一样。
  • 检查您是否使用“线程兼容”机制来处理对results的并发访问。可能是代码的semaphoremutex锁定原子部分。可能更好的是专用数据结构,例如queue

关于“挂”本身 - 请注意“打开网址”(urlopen)时的超时参数与时间有关 - 建立连接。不是为了下载实际数据:

  

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