2013-08-18 51 views
3

我剛開始研究python的管道方法。 我試圖將管道描述符包裝到文件對象中並逐行讀取。無法打開由Python中的線程創建的管道描述符

import os,time,threading 

def child(): 
    while True: 
     time.sleep(1) 
     msg = ('Spam\n').encode() 
     os.write(pipeout,msg) 


def parent(): 
    while True: 
     a = os.fdopen(pipein) 
     line = a.readline()[:-1] 
     print('Parent %d got [%s] at %s' % (os.getpid(),line,time.time())) 

pipein,pipeout = os.pipe() 

threading.Thread(target=child,args=()).start() 

parent() 

當我運行該腳本,結果如​​下----腳本只是工作在第一次迭代,然後會顯示錯誤消息

Parent 621 got [Spam] at 1376785841.4 
Traceback (most recent call last): 
    File "/Users/miteji/pipe-thread.py", line 43, in <module> 
    parent() 
    File "/Users/miteji/pipe-thread.py", line 36, in parent 
    line = a.readline()[:-1] 
IOError: [Errno 9] Bad file descriptor 
>>> Exception in thread Thread-1: 
Traceback (most recent call last): 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py",   line 551, in __bootstrap_inner 
    self.run() 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 504, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "/Users/miteji/pipe-thread.py", line 30, in child 
    os.write(pipeout,msg) 
OSError: [Errno 32] Broken pipe 

然而,當我改變

a = os.fdopen(pipein) 
line = a.readline()[:-1] 

line = os.read(pipein,32) 

腳本工作正常。

那麼爲什麼「os.fdopen」方法不能使用?爲什麼管道壞了?謝謝你們!

回答

1

的問題出在這裏os.fdopen安置:

def parent(): 
    while True: 
     a = os.fdopen(pipein) 
     line = a.readline()[:-1] 
     print('Parent %d got [%s] at %s' % (os.getpid(),line,time.time())) 

每通過循環之旅,你叫os.fdopen()再次,即使你以前那樣。

你第一次做的時候,你以前沒做過os.fdopen(),所以一切都很好。但是第二次,這將a重新綁定到新的結果,放棄較早的os.fdopen()值。

當較早的值被放棄時,它就有資格進行垃圾收集。 CPython立即通知(由於引用計數)並收集它。這將刪除底層對象,該對象調用os.fdclose()。這又會關閉管道。

要解決眼前的問題,請確保只在管路外打開一次管道。

+0

我明白了!有用!謝謝! – user2301339

相關問題