Python: 无法启动新线程。 <100个活动线程

11
我收到了以下错误信息:
----- Match 93028: ------ Patch 5.11 ------78 Threads Active
----- Match 93029: ------ Patch 5.11 ------77 Threads Active
----- Match 93030: ------ Patch 5.11 ------76 Threads Active
----- Match 93031: ------ Patch 5.11 ------71 Threads Active
----- Match 93032: ------ Patch 5.11 ------55 Threads Active
----- Match 93033: ------ Patch 5.11 ------56 Threads Active
----- Match 93034: ------ Patch 5.11 ------57 Threads Active
----- Match 93035: ------ Patch 5.11 ------58 Threads Active
----- Match 93036: ------ Patch 5.11 ------59 Threads Active
Traceback (most recent call last):
  File "pulldata.py", line 91, in <module>
    getPatchData('5.11', '511')
  File "pulldata.py", line 64, in getPatchData
    matchThread.start()
  File "/usr/lib/python3.4/threading.py", line 850, in start
    _start_new_thread(self._bootstrap, ())
RuntimeError: can't start new thread

通常这是由于打开了太多的线程所致,但您可以看到我也在打印活动线程数。当前有<100个活动线程,所以我不确定问题出在哪里。下面是相关代码:

slot = threading.BoundedSemaphore(value=1000)
def getMatchData(index,match,patch):
    global requestsSent
    global logfile
    print("----- Match {0}: ------ Patch {1} ------{2} Threads Active".format(index,patch,threading.active_count()))
    logfile.write("Parsing Match {0} for patch {1}:\n".format(index,patch))

    #match is a class. get is a function that sends a request to the server and returns a request object from where I get the json response.
    data = match.get().json()

    #processdata

    slot.release()

def getPatchData(patch, name):
    global logfile
    threads = []
    matches = getAllMatches(patch)
    for index, match in enumerate(matches):
        slot.acquire()
        matchThread = threading.Thread(target=getMatchData, args=(index,match,patch))
        threads.append(matchThread)
        matchThread.start()
        for t in threads:
            if not t.isAlive():
                threads.remove(t)

    for t in threads:
        t.join()

插槽信号量的作用是限制活动线程的数量,但我认为我从未达到过1000个线程。之前我认为这个错误是由于我的线程数组指向线程导致的,所以我添加了代码,在它们不再活动时将它们从数组中删除。
我无法理解为什么只有59个活动线程时就无法启动新线程。
此外,有没有更好的方法来实现我正在尝试做的事情?每个线程都向API发送请求。我尝试过不使用并发,但甚至无法接近我的速率限制。

尝试使用:队列 @hauzron https://docs.python.org/2/library/queue.html - dsgdfg
谢谢,那很有帮助,但现在我有一个内存泄漏问题:http://stackoverflow.com/questions/32286299/python-where-is-the-memory-leak - Hauzron
2个回答

8
我遇到了类似的问题,以下是我的解决方法。

不确定原作者使用的是什么操作系统,但在Linux上通常会限制每个用户的进程数量。 您可以通过ulimit -u(或者ulimit -a)来查看。 这个定义有点用词不当,因为实际上限制的是操作系统线程数量(或LWP)。 (参见:https://superuser.com/questions/376532/does-gnu-linux-counts-processes-and-threads-together-when-i-limit-their-number上的已采纳答案)

在我的系统上,限制似乎设置为400(但管理员可以更改它)。

您可以使用以下命令查看所有线程列表:

ps -fLu <your_username>

在我的例子中,我的python应用程序会引发与原作者报告的相同异常,但threading.active_count()会返回7。

原来我有许多来自以前会话的剩余进程(我使用nohup时有点过度热情...),每个进程有几个线程,在系统中挂起。删除它们就可以解决线程创建错误。

1
你是如何找到那些悬挂的线程的?我们也遇到了类似的问题。 - Abhishek Jain

1
我遇到了类似的情况,但我的进程需要大量线程运行。我使用以下命令计算线程数: ps -fLu 用户名 | wc -l
它显示了4098个线程。
我切换到该用户并查看系统限制:
sudo -u 我的用户名 -s /bin/bash ulimit -u
响应为4096。
因此,我编辑了/etc/security/limits.d/30-myuser.conf文件,并添加了以下行:
myuser hard nproc 8192
myuser soft nproc 8192
重新启动服务,现在它正在运行7017个线程。
附注:我有一个32核服务器,使用这种配置可以处理18000个同时连接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接