不在异常栈中显示Python的抛出行
当我在自己的Python库中抛出异常时,异常堆栈的最后一行显示的是我抛出异常的那一行。这显然不是错误,从概念上来说是对的,但在调试时,这个信息对外部使用代码的人来说并没有什么帮助,比如当你把它当作一个模块使用的时候。
有没有办法避免这种情况,让Python在异常堆栈中显示倒数第二行作为最后一行,就像标准的Python库那样?
3 个回答
我建议不要用异常机制来验证参数,虽然这样做很诱人。用异常来判断条件就像是在说:“如果作为开发者我没有考虑到我提供的参数可能导致的所有坏情况,那就让我的应用崩溃吧。”也许在处理那些不仅超出你控制范围的事情时,比如操作系统、硬件或Python语言本身,使用异常会更合理,我也不太确定。不过在实际操作中,我还是会像你要求的那样使用异常。
要回答你的问题,部分内容其实可以这样简单编码:
class MyObject(object):
def saveas(self, filename):
if not validate_filename(filename):
return False
...
调用者
if not myobject.saveas(filename): report_and_retry()
这可能不是一个很好的答案,但值得你思考一下。
你可以在Python中创建自己的异常处理钩子。下面是我使用的代码示例。
import sys
import traceback
def exceptionHandler(got_exception_type, got_exception, got_traceback):
listing = traceback.format_exception(got_exception_type, got_exception, got_traceback)
# Removing the listing of statement raise (raise line).
del listing[-2]
filelist = ["org.python.pydev"] # avoiding the debuger modules.
listing = [ item for item in listing if len([f for f in filelist if f in item]) == 0 ]
files = [line for line in listing if line.startswith(" File")]
if len(files) == 1:
# only one file, remove the header.
del listing[0]
print>>sys.stderr, "".join(listing)
以下是我在自定义异常代码中使用的一些代码行。
sys.excepthook = exceptionHandler
raise Exception("My Custom error message.")
在这个异常处理的方法中,你可以在“filenames”这个列表里添加文件名或模块名,如果你想忽略一些不需要的文件的话。比如,我就忽略了Python的pydev模块,因为我在Eclipse中使用的是pydev调试器。
上面的代码是我自己模块中特定用途的,你可以根据自己的需要进行修改并在你的模块中使用。
提醒一下:一般来说,修改解释器的行为是不太被推荐的。而且,知道错误发生的具体位置在调试时可能会很有帮助,特别是当一个函数可能因为多种原因引发错误时。
如果你使用traceback
模块,并用一个自定义的函数替换sys.excepthook
,理论上是可以做到的。不过,这样的修改会影响整个程序的错误显示,而不仅仅是你的模块,所以一般不建议这么做。
你也可以考虑把代码放在try/except块中,然后修改错误信息再重新抛出错误。但是,你可能更应该花时间去减少意外错误的发生,并为可能出现的错误编写清晰的信息。