错误:无法启动新线程

2024-04-28 20:55:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个运行以下配置的站点:

Django+mod wsgi+apache

在用户的一个请求中,我向另一个服务发送另一个HTTP请求,并通过python的httplib库解决这个问题。

但有时这个服务不会得到太长的应答,httplib的超时也不起作用。所以我创建了线程,在这个线程中我向服务发送请求,并在20秒后加入它(20秒-是请求超时)。这就是它的工作原理:

class HttpGetTimeOut(threading.Thread):
    def __init__(self,**kwargs):
        self.config = kwargs
        self.resp_data = None
        self.exception = None
        super(HttpGetTimeOut,self).__init__()
    def run(self):

        h = httplib.HTTPSConnection(self.config['server'])
        h.connect()
        sended_data = self.config['sended_data']
        h.putrequest("POST", self.config['path'])
        h.putheader("Content-Length", str(len(sended_data)))
        h.putheader("Content-Type", 'text/xml; charset="utf-8"')
        if 'base_auth' in self.config:
            base64string = base64.encodestring('%s:%s' % self.config['base_auth'])[:-1]
            h.putheader("Authorization", "Basic %s" % base64string)
        h.endheaders()

        try:
            h.send(sended_data)
            self.resp_data = h.getresponse()
        except httplib.HTTPException,e:
            self.exception = e
        except Exception,e:
            self.exception = e

像这样的。。。

通过这个函数使用它:

getting = HttpGetTimeOut(**req_config)
getting.start()
getting.join(COOPERATION_TIMEOUT)
if getting.isAlive(): #maybe need some block
    getting._Thread__stop()
    raise ValueError('Timeout')
else:
    if getting.resp_data:
        r = getting.resp_data
    else:
        if getting.exception:
            raise ValueError('REquest Exception')
        else:
            raise ValueError('Undefined exception')

一切都很好,但有时我会发现一个例外:

error: can't start new thread

在开始新线程的行:

getting.start()

下一条也是最后一条回溯线是

File "/usr/lib/python2.5/threading.py", line 440, in start
    _start_new_thread(self.__bootstrap, ())

答案是:发生了什么事?

谢谢大家,对不起我纯正的英语。:)


Tags: selfconfigdataifexception线程respstart
3条回答

我认为最好的方法是设置套接字超时而不是生成线程:

h = httplib.HTTPSConnection(self.config['server'], 
                            timeout=self.config['timeout'])

还可以使用^{}函数设置全局默认超时。

更新:请参阅Is there any way to kill a Thread in Python?问题的答案(这里有几个信息量很大的问题)以了解原因。Thread.__stop()不终止线程,而是设置内部标志,使其被视为已停止。

您启动的线程超过了系统可以处理的线程数。对于一个进程,可以激活的线程数是有限制的。

应用程序启动线程的速度比线程运行到完成的速度快。如果你需要启动许多线程,你需要以一种更可控的方式来完成,我建议你使用一个线程池。

“无法启动新线程”错误几乎肯定是由于您的python进程中已经有太多线程在运行,并且由于某种资源限制,创建新线程的请求被拒绝。

您可能应该查看正在创建的线程数;您将能够创建的最大线程数将由您的环境决定,但至少应该是数百个线程的顺序。

在这里重新考虑您的体系结构可能是一个好主意;鉴于这无论如何都是异步运行的,也许您可以使用一个线程池从另一个站点获取资源,而不是总是为每个请求启动一个线程。

另一个需要考虑的改进是使用Thread.join和Thread.stop;这可能通过向HTTPSConnection的构造函数提供超时值来更好地实现。

相关问题 更多 >