Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
抑制“打印输出”;例外。。。“忽略”;Python 3中的消息_Python_Bash_Python 2.7_Python 3.x - Fatal编程技术网

抑制“打印输出”;例外。。。“忽略”;Python 3中的消息

抑制“打印输出”;例外。。。“忽略”;Python 3中的消息,python,bash,python-2.7,python-3.x,Python,Bash,Python 2.7,Python 3.x,Python中有一个已知的问题,其中:;也见于 我想做的是,当这个问题发生时,在Python2.7和Python3+中打印出相同的自定义消息。因此,我准备了一个测试脚本,testprint.py并运行它(在Ubuntu 11.04的bash中显示的代码片段): 好的,越来越近了。。。现在,“忽略”这些异常(或者在我的情况下,替换为自定义错误消息)的方法是处理它们: >有没有办法让[解释器]忽略异常。 不。要么处理异常,要么编写不处理的代码 生成异常 。。。如前所述,实现这一点的方法是try/e

Python中有一个已知的问题,其中:;也见于

我想做的是,当这个问题发生时,在Python2.7和Python3+中打印出相同的自定义消息。因此,我准备了一个测试脚本,
testprint.py
并运行它(在Ubuntu 11.04的
bash
中显示的代码片段):

好的,越来越近了。。。现在,“忽略”这些异常(或者在我的情况下,替换为自定义错误消息)的方法是处理它们:

>有没有办法让[解释器]忽略异常。
不。要么处理异常,要么编写不处理的代码 生成异常

。。。如前所述,实现这一点的方法是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

$cat>testprint.py只是关于这个问题的更多说明-问题仍然没有解决。。。第一:

此错误消息是在PyErr_WriteUnraisable中生成的,它是 从许多上下文调用,包括_del__方法。A _del _方法 在关机过程中调用的最有可能是生成错误的原因 但是据我所知_del_________________________________ 尤其要知道,在关机期间正在调用它。所以 建议的邮件修复程序将不起作用。[…]
然而,因为这是一条信息,所以您甚至无法捕获它 改变它应该是完全安全的

好的,谢谢你的这条消息,你不能陷阱,非常方便。我相信这在某种程度上与之相关,尽管那篇文章(显然)谈到了定制的
\uu del\uu
方法

使用以下一些资源:

。。。我修改了脚本,因此我重载了所有可能的处理程序,以查看是否有空间可以“处理”此异常,从而使其不会被“忽略”:

请注意此脚本运行方式的差异:

$ python2.7 testprint.py | echo

signalPIPE_handler!(None, None, None)
_trace exc frame: testprint.py 44 <function _trace at 0xb748e5dc>(<type 'exceptions.IOError'>, (32, 'Broken pipe'), <traceback object at 0xb748acac>)
myexcepthook
 IOError intraceback:
  File "testprint.py", line 44, in main
    sys.stdout.flush()
_trace exc frame: testprint.py 51 None(<type 'exceptions.IOError'>, (32, 'Broken pipe'), <traceback object at 0xb748acac>)
myexcepthook
 IOError intraceback:
  File "testprint.py", line 44, in main
    sys.stdout.flush()
Exc: <type 'exceptions.IOError'>
Exiting

$ python3.2 testprint.py | echo

signalPIPE_handler!(None, None, None)
_trace exc frame: testprint.py 44 <function _trace at 0xb74247ac>(<class 'IOError'>, (32, 'Broken pipe'), <traceback object at 0xb747393c>)
myexcepthook
 IOError intraceback:
  File "testprint.py", line 44, in main
    sys.stdout.flush()
_trace exc frame: testprint.py 51 None(<class 'IOError'>, (32, 'Broken pipe'), <traceback object at 0xb747393c>)
myexcepthook
 IOError intraceback:
  File "testprint.py", line 44, in main
    sys.stdout.flush()
Exc: <class 'IOError'>
signalPIPE_handler!(None, None, None)
Exiting
signalPIPE_handler!(None, None, None)
Exception IOError: (32, 'Broken pipe') in <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> ignored
在这里它会阻塞;在同一方向的另一个终端中,执行以下操作:

$ echo <foo
不幸的是,我现在无法从源代码构建Python3并进行调试;因此,我希望知道
:)


干杯

此错误消息是Python发出的,指示提供的管道定义被破坏,尽管有点混乱(请参阅)

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

如果您知道您不关心用例中的管道破裂,那么可以在程序结束之前显式关闭
stdout
来处理这种情况。它仍然会抱怨管道破裂,但它会以一种让您能够像往常一样捕获和抑制异常的方式进行:

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()
在这个版本中,只看到预期的输出,因为即使尝试关闭它也足以确保在解释器关闭期间流已经标记为关闭:

$ python3 testprint.py | echo

Exc: <class 'BrokenPipeError'>
Exc on close: <class 'BrokenPipeError'>
$python3 testprint.py | echo
执行委员会:
行政会议闭幕:

这是一个非常丑陋的黑客行为,它可以在打印到标准输出导致管道破裂的情况下抑制错误消息的显示(例如,因为调用了类似
your-program.py | less
的寻呼机进程,但没有滚动到输出的底部:

try:
    actual_code()
except BrokenPipeError:
    sys.stdout = os.fdopen(1)

它适用于我的head、tail、less、more和unique,因此看起来在与echo的交互中有一个实际的bug。当解释器关闭时,当它试图再次刷新标准流时,“异常被忽略”部分实际上发生了。
$ echo <foo
...
Starting program: /usr/bin/python3.2 testprint.py > foo
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".

Program received signal SIGPIPE, Broken pipe.
0x0012e416 in __kernel_vsyscall ()
(gdb) bt
#0  0x0012e416 in __kernel_vsyscall ()
#1  0x0013c483 in __write_nocancel () from /lib/i386-linux-gnu/libpthread.so.0
#2  0x0815b549 in ?? ()
#3  0x08170507 in ?? ()
#4  0x08175e43 in PyObject_CallMethodObjArgs ()
#5  0x0815df21 in ?? ()
#6  0x0815f94e in ?? ()
#7  0x0815fb05 in ?? ()
#8  0x08170507 in ?? ()
#9  0x08175cb1 in _PyObject_CallMethod_SizeT ()
#10 0x08164851 in ?? ()
#11 0x080a3a36 in PyEval_EvalFrameEx ()
#12 0x080a3a53 in PyEval_EvalFrameEx ()
#13 0x080a43c8 in PyEval_EvalCodeEx ()
#14 0x080a466f in PyEval_EvalCode ()
#15 0x080c6e9d in PyRun_FileExFlags ()
#16 0x080c70c0 in PyRun_SimpleFileExFlags ()
#17 0x080db537 in Py_Main ()
#18 0x0805deee in main ()
(gdb) finish
Run till exit from #0  0x0012e416 in __kernel_vsyscall ()
0x0013c483 in __write_nocancel () from /lib/i386-linux-gnu/libpthread.so.0
...
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()
$ python3 testprint.py | echo

Exc: <class 'BrokenPipeError'>
Exc on close: <class 'BrokenPipeError'>
try:
    actual_code()
except BrokenPipeError:
    sys.stdout = os.fdopen(1)