Python在线程中调用pipe.communicate()

Python在线程中调用pipe.communicate(),python,multithreading,deadlock,multiprocessing,Python,Multithreading,Deadlock,Multiprocessing,在Mac OS X 10.6.2上使用Python 2.6.1时,我遇到以下问题: 我有一个线程进程(线程类),每个线程都有一个管道(subprocess.Popen),类似于: from threading import Thread cmd = "some_cmd" class Worker(Thread): def run(self): pipe = Popen(cmd, stdin=PIPE, stdout=PIPE,

在Mac OS X 10.6.2上使用Python 2.6.1时,我遇到以下问题:

我有一个线程进程(线程类),每个线程都有一个管道(subprocess.Popen),类似于:

 from threading import Thread

 cmd = "some_cmd"

 class Worker(Thread):
    def run(self):
       pipe = Popen(cmd,
        stdin=PIPE,
        stdout=PIPE,
        stderr=PIPE)

       out, err = pipe.communicate("some data")
问题在于pipe.communicate()代码被阻塞。有趣的是,当我向父进程发送一个中断(例如,
Ctrl-C
KeyboardInterrupt)时,它就会解锁

有趣的是,当我使用
类工作者(multiprocessing.Process)
时,代码工作得很好

如果您有任何想法想知道为什么会出现阻塞,以及如何修复,我们将不胜感激


谢谢。

使用多线程和多进程通常会导致问题,尤其是在基于Unix的系统上(尽管不是唯一的);我建议您避免将两者混合使用。

如果在主线程中调用
sys.exit()
,其他线程将在下一次机会终止(在大多数操作系统上)。但是,如果它们处于阻塞调用(如communicate())中,它们将等待阻塞调用完成后再终止。Control-C之所以工作,是因为它会导致操作系统中断阻塞调用

通常,最安全的方法是确保没有线程调用可能无限阻塞的函数。不幸的是,这通常需要编写更多的代码

在您的特定情况下,您可以在调用communicate之前将
Popen
对象存储在全局
set()
中,并在退出之前对每个对象进行主线程调用
Popen.terminate()
。这将导致子线程退出,
communicate()
返回,线程退出


您是否将该线程设置为线程?

刚刚找到-但是我不确定(目前)修复的是什么!看起来Popen可能不是线程安全的。非常有义务改正或澄清。在主题上找到。Communication()应阻止。你的意思是它阻塞了整个程序,而不仅仅是它运行的线程?您能提供一个完整的示例程序吗?@Daniel Stutzbach:
通信
正在阻塞,即使进程确实(或应该)终止。Daniel Stutzbach:因为这个问题,我放弃了,回到了
多处理。进程
(它没有阻止
通信
)采用完全不同的设计,所以我无法从内存中复制测试用例。唉,这个问题的原因仍然是个谜,但我强烈怀疑这是因为
Popen
调用不是线程安全的,因为它的唯一区别是它是
threading.thread
而不是
multiprocessing.Process
。在前一种情况下,
communicate
被阻止(如果这是正确的词),但在后一种情况下,它按预期终止。