Python线程挂起

Jer*_*rry 10 python multithreading multiprocessing python-multithreading

我有一个遵循标准范例的简单线程Python程序:

class SearchThread(threading.Thread):
    def __init__(self, search_queue):
        threading.Thread.__init__(self)
        self.search_queue = search_queue

    def run(self):
        while True:
            try:
                search_url = self.search_queue.get(timeout=15)
                # <do Internet search and print output/>
            except Queue.Empty:
                self.search_queue.task_done()
                break
            except Exception, e:
                print e

if __name__ == '__main__':
    search_queue = Queue.Queue()    
    for i in range(200):
        t = SearchThread(search_queue)
        t.setDaemon(True)
        t.start()
    search_queue.join()
Run Code Online (Sandbox Code Playgroud)

队列中填充了大约1000个URL并且HTTP GET执行简单<do Internet search and print output/>.问题是,在处理了大约500-700个条目(只需几秒钟)之后,程序会一直挂起,没有输出,没有例外,没有任何内容.

我试过requests,urllib2,urllib3,httplib2HTTP GET但没有改变.

你如何调试挂起的线程Python程序?

顺便说一句,我在Ubuntu 11.10(64位)下使用Python 2.7.

编辑

当我盯着挂起过程中的gdb跟踪时,我和以前一样无能为力 -

sudo gdb python 9602
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
...
(gdb) where
#0  0x00007fc09ea91300 in sem_wait () from /lib/x86_64-linux-gnu/libpthread.so.0
#1  0x00000000004ed001 in PyThread_acquire_lock ()
#2  0x00000000004f02de in ?? ()
#3  0x00000000004b6569 in PyEval_EvalFrameEx ()
#4  0x00000000004bcd2d in PyEval_EvalCodeEx ()
#5  0x00000000004b6a5b in PyEval_EvalFrameEx ()
#6  0x00000000004b6d77 in PyEval_EvalFrameEx ()
#7  0x00000000004bcd2d in PyEval_EvalCodeEx ()
#8  0x00000000004bd802 in PyEval_EvalCode ()
#9  0x00000000004dcc22 in ?? ()
#10 0x00000000004dd7e4 in PyRun_FileExFlags ()
#11 0x00000000004de2ee in PyRun_SimpleFileExFlags ()
#12 0x00000000004ee6dd in Py_Main ()
#13 0x00007fc09d86030d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#14 0x000000000041cb69 in _start ()
Run Code Online (Sandbox Code Playgroud)

Use*_*ser 14

我写了一个模块,打印出在一个地方挂了10秒钟的线程. hanging_threads.py()

这是一个示例输出:

--------------------    Thread 5588     --------------------
  File "C:\python33\lib\threading.py", line 844, in _exitfunc
        t.join()
  File "C:\python33\lib\threading.py", line 743, in join
        self._block.wait()
  File "C:\python33\lib\threading.py", line 184, in wait
        waiter.acquire()
Run Code Online (Sandbox Code Playgroud)

当您忘记将另一个线程设置为守护进程时,会在主线程的出口处发生这种情况.

  • 真好!但请注意,如果Python GIL涉及死锁,它将无法工作.在这种情况下,一旦挂起,就不会再执行Python代码了.要解决这个问题,您需要在C中实现相同的功能,而不需要Python GIL.它变得棘手:要安全地执行它,您需要暂停所有线程.一种相对简单的方法是发出信号并在信号处理程序中执行.如果您对某些代码感兴趣,我在[我的MusicPlayer项目](https://github.com/albertz/music-player)中做了很多这些事情. (3认同)

Mak*_*cha 0

你的 while 循环是无限的。即使队列为空,线程也永远不会完成执行。您应该检查队列中是否有新任务,或者通知线程(例如使用事件)不需要任何任务。