Python 中有一个已知问题,当 stdout 上发生“Broken pipe”时,“close failed in file object destructor” - Python tracker Issue 11380;在 python 中也可以看到- 为什么我的 Python3 脚本在将其输出传送到头部或尾部(sys 模块)时犹豫不决?- 堆栈溢出。
我想要做的是在 Python 2.7 和 Python 3+ 发生此问题时打印出相同的自定义消息。所以我准备了一个测试脚本,testprint.py
并运行它(在bash
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 pipeline 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
好的,越来越近了......现在,“忽略”这些异常(或者在我的情况下,用自定义错误消息替换)的方法是处理它们:
> 有什么方法可以让[解释器] 忽略异常。
没有。要么处理异常,要么编写不生成异常的代码。
...正如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
不再打印?