禁止打印“例外...已忽略";Python 3中的消息 [英] Suppressing printout of "Exception ... ignored" message in Python 3

查看:70
本文介绍了禁止打印“例外...已忽略";Python 3中的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python中存在一个已知的问题,其中"在文件对象析构函数中关闭失败""发生在stdout上-Python跟踪器问题11380 ;在

There is a known issue in Python, where "close failed in file object destructor" when "Broken pipe" happens on stdout - Python tracker Issue 11380; also seen in 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 并运行它(在Ubuntu 11.04的 bash 中显示的代码片段):

What I want to do, is printout the same custom message when this problem happens, in both Python 2.7 and Python 3+. So I prepare a test script, testprint.py and run it (snippets shown done in 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

与上面的链接一样,有两种不同的消息.在关于管道错误的帮助(velocityreviews.com),建议使用 sys.stdout.flush()强制Python 2注册IOError而不是该消息;有了,我们有:

As expected from above links, there are two different messages. In Help with a piping error (velocityreviews.com), it is recommended to use sys.stdout.flush() to force Python 2 to register an IOError instead of that message; with that, we have:

$ 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

好的,越来越近...现在,忽略"这些异常的方法(在我的情况下,用自定义错误消息替换)是处理它们:

OK, getting closer... Now, the way to "ignore" these exceptions (or in my case, replace with a custom error message), is to handle them:

忽略异常-comp.lang.python

>有什么方法可以使[解释器]忽略异常.
不.处理异常或编写不执行的代码生成异常.

> Is there any way to make [interpreter] ignore exceptions.
Nope. Either handle the exceptions or write code that doesn't generate exceptions.

...和 Python简介-处理异常注意,执行此操作的方法是try/except块.因此,让我们尝试一下:

... and as An Introduction to Python - Handling Exceptions notes, the way to do that is a try/except block. So let's try that:

$ 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 ...忽略留言!有什么问题-" IOError 除外"对于Python 3来说还不够吗?但这必须是-否则就不会打印自定义的" Exc:... "消息!

Ok, so try/except works as I expect it for Python 2.7 - but then, Python 3.2 both handles as expected, and still generates a Exception ... ignored message! What's the problem - isn't "except IOError" enough for Python 3? But it must be - otherwise it wouldn't have printed the custom "Exc:..." message!

所以-这是什么问题,为什么即使我正在处理异常,Python 3仍然打印 Exception ... ...忽略了?而且更重要的是,如何处理它,以便 不再打印 Exception ...被忽略的 ?

So - what is the problem here, and why is the Exception ... ignored still printed in Python 3, even if I'm handling the exception? And more importantly, how do I handle it so the Exception ... ignored does not get printed anymore?

推荐答案

此错误消息是Python,表示所提供的管道定义已损坏,尽管有些混乱(请参阅

This error message is Python indicating that the supplied pipeline definition is broken, albeit in a somewhat confusing way (see http://bugs.python.org/issue11380)

echo实际上并不接受通过stdin进行的输入,因此来自Python的输入管道最终会提前关闭.您看到的额外异常(异常处理程序之外)是由于在解释器关闭时隐式尝试刷新标准流.发生这种情况超出了任何用户提供的Python代码的范围,因此解释器只是将错误写到 stderr 而不是调用普通的异常处理.

echo doesn't actually accept input via stdin, so the input pipe from Python ends up being closed early. The extra exception you're seeing (outside the exception handler) is then due to the implicit attempt to flush the standard streams as the interpreter is shutting down. This happens outside the scope of any user provided Python code, so the interpreter just writes the error to stderr rather than invoking normal exception processing.

如果您知道自己不关心用例的管道中断,可以通过在程序结束之前显式关闭 stdout 来处理这种情况.它仍然会抱怨管道损坏,但是它会以一种使您像往常一样捕获和抑制异常的方式来做到这一点:

If you know you don't care about broken pipes for your use case, you can deal with this case by explicitly closing stdout before the end of your program. It will still complain about the broken pipe, but it will do it in a way that lets you catch and suppress the exception as usual:

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")
  try:
    sys.stdout.close()
  except IOError:
    sys.stderr.write("Exc on close: " + str(sys.exc_info()[0]) + "\n")

if __name__ == "__main__":
  main()

在此版本中,仅看到预期的输出,因为即使尝试关闭它也足以确保在解释器关闭期间流已被标记为已关闭:

In this version, only the expected output is seen, because even the attempt at closing it is enough to ensure the stream is already marked as closed during interpreter shutdown:

$ python3 testprint.py | echo

Exc: <class 'BrokenPipeError'>
Exc on close: <class 'BrokenPipeError'>

这篇关于禁止打印“例外...已忽略";Python 3中的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆