2

以下代码在通过管道传输到 tee 时以损坏的管道结尾,但在未通过管道传输时行为正确:

#!/usr/bin/python
import sys
def testfun():
    while 1:
        try :
            s = sys.stdin.readline()
        except(KeyboardInterrupt) :
            print('Ctrl-C pressed')
            sys.stdout.flush()
            return
        print s

if __name__ == "__main__":
    testfun()
    sys.exit()

预期输出:

./bug.py 
Ctrl-C pressed

当管道进入 tee 时观察到的是管道损坏或根本没有输出,即 tee 标准输出上没有任何内容,而 bug.log 中没有任何内容:

./bug.py | tee bug.log
Traceback (most recent call last):
  File "./bug.py", line 14, in <module>
    sys.stdout.flush()
IOError: [Errno 32] Broken pipe

这可能是什么原因?

4

3 回答 3

9

不,按 Ctrl-C 不会终止这两个进程。它仅终止 tee 进程,tee 进程的结束关闭脚本和 tee 之间的管道,因此您的脚本因管道消息中断而死亡。

为了解决这个问题, tee 可以选择将 Ctrl-C 传递给管道中的前一个进程:-i

尝试:男士三通

./bug.py
^CCtrl-C pressed
./bug.py | tee log
^CTraceback (most recent call last):
  File "./bug.py", line 14, in <module>
    testfun()
  File "./bug.py", line 9, in testfun
    sys.stdout.flush()
IOError: [Errno 32] Broken pipe

./bug.py | tee -i log
^CCtrl-C pressed
于 2011-08-31T00:52:17.033 回答
5

这不是 python 问题,而是 shell 问题,正如 Brian 指出的那样,按 Ctrl-C 将终止这两个进程。解决方法是使用命名管道:

mknod mypipe p
cat mypipe | tee somefile.log &
./bug.py > mypipe
于 2009-07-28T09:25:35.077 回答
4

当您按下 Ctrl-C 时,shell 将终止两个进程(pythontee)并拆除连接它们的管道。

因此,当您在python进程中处理 Ctrl-C 并刷新时,它会发现tee已终止并且管道不再存在。因此出现错误消息。

(顺便说一句,您是否期望日志中有任何内容?我没有看到您的进程在退出时输出除了刷新之外的任何内容)

于 2009-07-28T09:10:07.840 回答