尝试将Python程序用管道命令输出到cd时报错 - sys.excepthook is missing lost sys.stderr

在stackoverflow上找到了答案:

NB: I have not attempted to reproduce the problem described below under Windows, or with versions of Python other than 2.7.3.

The most reliable way to elicit the problem in question is to pipe the output of the following test script through : (under bash):

try:
    for n in range(20):
        print n
except:
    pass

I.e.:

% python testscript.py | :
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr

My question is:

How can I modify the test script above to avoid the error message when the script is run as shown (under Unix/bash)?

(As the test script shows, the error cannot be trapped with a try-except.)

The example above is, admittedly, highly artificial, but I'm running into the same problem sometimes when the output of a script of mine is piped through some 3rd party software.

The error message is certainly harmless, but it is disconcerting to end-users, so I would like to silence it.

EDIT: The following script, which differs from the original one above only in that it redefines sys.excepthook, behaves exactly like the one given above.

import sys
STDERR = sys.stderr
def excepthook(*args):
    print >> STDERR, 'caught'
    print >> STDERR, args

sys.excepthook = excepthook

try:
    for n in range(20):
        print n
except:
    pass


How can I modify the test script above to avoid the error message when the script is run as shown (under Unix/bash)?

You will need to prevent the script from writing anything to standard output. That means removing any print statements and any use of sys.stdout.write, as well as any code that calls those.

The reason this is happening is that you're piping a nonzero amount of output from your Python script to something which never reads from standard input. This is not unique to the : command; you can get the same result by piping to any command which doesn't read standard input, such as

python testscript.py | cd .

Or for a simpler example, consider a script printer.py containing nothing more than

print 'abcde'

Then

python printer.py | python printer.py

will produce the same error.

When you pipe the output of one program into another, the output produced by the writing program gets backed up in a buffer, and waits for the reading program to request that data from the buffer. As long as the buffer is nonempty, any attempt to close the writing file object is supposed to fail with an error. This is the root cause of the messages you're seeing.

The specific code that triggers the error is in the C language implementation of Python, which explains why you can't catch it with a try/except block: it runs after the contents of your script has finished processing. Basically, while Python is shutting itself down, it attempts to close stdout, but that fails because there is still buffered output waiting to be read. So Python tries to report this error as it would normally, but sys.excepthook has already been removed as part of the finalization procedure, so that fails. Python then tries to print a message to sys.stderr, but that has already been deallocated so again, it fails. The reason you see the messages on the screen is that the Python code does contain a contingency fprintf to write out some output to the file pointer directly, even if Python's output object doesn't exist.

I can provide details of the relevant parts of the C code if you're interested.


深为折服,很深刻很到位。

学习到了几点,陈列如下:

1. 管道命令 | 是将数据由标准输出STDOUT流向标准输入STDIN,因此不向STDIN读取数据的命令无法通过管道命令获取数据。(准确否?)

2. cd命令是通过终端的命令行(设备[键盘]输入?)读取数据的,所以 python <pythonScript.py> | cd 会失败。

3. 那如何向诸如cd这样的命令传值呢?

引用鸟叔的《Linux私房菜》第11章中的内容:“在一串命令中,还需要通过其他的命令提供的信息,可以使用反单引号“`命令`”或“$(命令)。””



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值