2010-03-30 51 views
3

在Mac OS X 10.6.2使用Python 2.6.1,我以下的問題:Python的調用pipe.communicate()在一個線程

我有一個螺紋加工(Thread類),每那些線程的具有管(subprocess.Popen)東西likeso:

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)時,它會解除阻塞。

有趣的是,當我使用class Worker(multiprocessing.Process)時,代碼工作得很好。

任何想法爲什麼這是阻止- 以及如何解決它 -將不勝感激。

謝謝。

+0

剛剛找到http://stackoverflow.com/questions/984941/python-subprocess-popen-from-a-thread - 但我不知道從那是什麼修復(還)! – 2010-03-30 02:08:48

+0

看起來像Popen可能不是線程安全的。非常有義務進行更正或澄清。找到有關該主題的http://mail.python.org/pipermail/python-bugs-list/2007-August/039177.html。 – 2010-03-30 02:14:07

+0

溝通()是*假設*阻止。你的意思是它阻止了整個程序,而不是它正在運行的線程?你能提供一個完整的示例程序嗎? – 2010-03-30 04:37:45

回答

1

如果您在主線程中調用sys.exit(),其他線程將在下一個機會(在大多數操作系統上)終止。但是,如果它們處於阻塞呼叫(例如communications())中,它們將等到阻塞呼叫完成後再終止。 Control-C可以工作,因爲它會導致操作系統中斷阻塞呼叫。

通常,最安全的方法是確保您的線程都不會調用可能無限期阻塞的函數。不幸的是,這通常需要編寫更多的代碼。

在您的特定情況下,可以在全球set()Popen對象存儲電話通信之前,只是在退出之前對他們每個人的主線程調用Popen.terminate()。這會導致孩子退出,communicate()返回,並退出線程。

您是否將線程設置爲daemon線程?

1

使用多線程多進程通常會導致問題,特別是(儘管不是唯一的)在基於Unix的系統上;我建議你避免混淆兩者。

相關問題