忘了重定向stderr导致的某问题

最近某python程序常常抛exception。而且比较神奇的是,貌似这个exception是一层层抛出来的。
先是最内层except块打的log,然后是次外层,然后是再外面……
我本来写的代码并不会重抛异常,所以这很神奇……
except块大约是这样的:

except Exception as e:
    Log.error("send error: %r" % e)
    traceback.print_exc()

能看见第一行的log,但是之后print_exc()的结果就没了。下一行log是更外面的except块的log……

于是这个大概就是print_exc()抛的异常,但是这个东西能抛啥……
之后想了一下,就算是异常一路抛到最外面,也应该有个backtrace,而log里啥都没有……
想想backtrace是打到stderr的,难道stderr没有重定向……
之后再看了一眼,log是打到stdout的…… 再去看启动python程序的脚本,貌似只重定向了stdout,忘了重定向stderr了……

难道断了的stderr不能写?我又写了个小程序ssh到服务器上跑:

#!/usr/bin/env python
 
import sys
import time
 
time.sleep(10)
 
try:
    sys.stderr.write('test\n')
except Exception as e:
    print "Exception: %r" % e

python test.py > tmp.txt &

跑,跑起来就断ssh。过会上去一看,果然出了个Exception,IOError(5, ‘Input/Output error’)……

到这儿差不多就弄清楚了。因为我是ssh到服务器跑程序,所以弄了个脚本重定向输出的log文件里。、
但是脚本写错了,没有重定向stderr。所以stderr接到了console上。
等我把ssh一断,stderr另一头就断了。
过了若干时间之后,程序出了个exception。在print_exc()的时候,程序尝试写stderr。但是因为stderr挂了,抛了个IOError。
因为每层except都调了print_exc(),每层都抛出了个新的IOError给下一层……
于是就一路抛到了最外面……

既然知道了就好修。
首先嘛,自然要修正脚本,把stderr一起重定向了。
其次嘛,虽说不是必要,不用print_exc()转而用format_exc()然后扔给Log.error()了。
理论上log都应该直接打到文件,或者至少错误类消息应该打到stderr去。不过反正是服务器程序,stdout也没啥用,再说……

当然,这些都没修正根本问题。其实最初的exception是意料之中的,不过还是应该修正一下让它不抛才是……

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.