【发布时间】:2013-04-25 05:24:05
【问题描述】:
Python 中有一个已知问题,"close failed in file object destructor" when "Broken pipe" happens on stdout - Python tracker Issue 11380;也见于python - Why does my Python3 script balk at piping its output to head or tail (sys module)? - Stack Overflow。
我想要做的是在 Python 2.7 和 Python 3+ 发生此问题时打印出相同的自定义消息。所以我准备了一个测试脚本,testprint.py 并运行它(在bash 中显示的 sn-ps,Ubuntu 11.04):
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py
Hello Hello Hello Hello Hello
$ python2.7 testprint.py | echo
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
$ python3.2 testprint.py | echo
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
正如上述链接所预期的,有两种不同的消息。在Help with a piping error (velocityreviews.com) 中,建议使用sys.stdout.flush() 来强制Python 2 注册一个IOError 而不是那个消息;有了这个,我们有:
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
$ python3.2 testprint.py | echo
Traceback (most recent call last):
File "testprint.py", line 9, in <module>
main()
File "testprint.py", line 6, in main
sys.stdout.flush()
IOError: [Errno 32] Broken pipe
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
好的,越来越近了……现在,“忽略”这些异常(或者在我的情况下,用自定义错误消息替换)的方法是处理它们:
Ignore exceptions - comp.lang.python
> 有什么方法可以让 [interpreter] 忽略异常。
没有。要么处理异常,要么编写不处理异常的代码 生成异常。
...正如An Introduction to Python - Handling Exceptions 所说,这样做的方法是使用try/except 块。所以让我们尝试一下:
$ cat > testprint.py <<"EOF"
import sys
def main():
teststr = "Hello " * 5
try:
sys.stdout.write(teststr + "\n")
sys.stdout.flush()
except IOError:
sys.stderr.write("Exc: " + str(sys.exc_info()[0]) + "\n")
if __name__ == "__main__":
main()
EOF
$ python2.7 testprint.py | echo
Exc: <type 'exceptions.IOError'>
$ python3.2 testprint.py | echo
Exc: <class 'IOError'>
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
好的,所以 try/except 在 Python 2.7 中可以正常工作 - 但是,Python 3.2 都按预期处理,并且仍然会生成 Exception ... ignored 消息!有什么问题 - “except IOError”对于 Python 3 来说还不够吗?但它必须是——否则它不会打印自定义的“Exc:...”消息!
那么 - 这里有什么问题,为什么Exception ... ignored 仍然打印在 Python 3 中,即使我正在处理异常?更重要的是,我该如何处理它以使 Exception ... ignored 不再 不再打印?
【问题讨论】:
-
它适用于我的 head、tail、less、more 和 unique 所以看起来在与 echo 的交互中存在一个实际的错误。 “忽略异常”部分实际上是在解释器关闭期间尝试再次刷新标准流时发生的。
标签: python bash python-2.7 python-3.x