无法在Python中打开由线程创建的管道描述符

3

我刚开始学习 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]

to

line = os.read(pipein,32)

这个脚本运行正常。

为什么不能使用"os.fdopen"方法?为什么管道断开了?谢谢大家!

1个回答

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()。这反过来关闭了管道。

为了解决问题,请确保只在循环外打开管道一次。


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