python:我如何知道发生了什么类型的异常?
我有一个主程序调用的函数:python:我如何知道发生了什么类型的异常?,python,exception,Python,Exception,我有一个主程序调用的函数: try: someFunction() except: print "exception happened!" 但是在执行函数的中间,它引发异常,所以它跳到代码> 部分。 我怎样才能准确地看到导致异常发生的someFunction()中发生了什么?通常不应该使用try:>捕获所有可能的异常。。。除了,因为这太宽泛了。不管出于什么原因,只要抓住那些可能发生的事情。如果您确实必须这样做,例如,如果您想在调试时了解有关某个问题的更多信息,您应该这样做 tr
try:
someFunction()
except:
print "exception happened!"
但是在执行函数的中间,它引发异常,所以它跳到<>代码> 部分。
我怎样才能准确地看到导致异常发生的
someFunction()
中发生了什么?通常不应该使用try:>捕获所有可能的异常。。。除了
,因为这太宽泛了。不管出于什么原因,只要抓住那些可能发生的事情。如果您确实必须这样做,例如,如果您想在调试时了解有关某个问题的更多信息,您应该这样做
try:
...
except Exception as ex:
print ex # do whatever you want for debugging.
raise # re-raise exception.
可以通过以下方式捕获实际异常:
try:
i = 1/0
except Exception as e:
print e
您可以从中了解有关异常的更多信息。其他答案都指出,您不应该捕获一般异常,但似乎没有人想告诉您原因,这对于理解何时可以打破“规则”至关重要。这是一种解释。基本上,这样你就不会隐藏:
- 发生错误的事实
- 发生的错误的详细信息()
- 在GUI中将异常显示为对话框
- 在多线程或多处理应用程序中,将异常从工作线程或进程转移到控制线程或进程
try:
someFunction()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print message
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
File "exc.py", line 7, in <module>
raise CustomException("hi")
CustomException: hi
确保消息
以一种不容错过的方式引起用户的注意!如上图所示,如果消息被隐藏在许多其他消息中,打印它可能是不够的。没有引起用户的注意就等于吞没了所有的例外,如果你在阅读了本页的答案后有一种印象应该消失,那就是这不是一件好事。用raise
语句结束except块将通过透明地重新调用捕获的异常来解决问题
以上与仅使用除外:
而不使用任何参数之间的区别有两方面:
- 裸
不会提供要检查的异常对象except:
- 上述代码通常不会捕获异常
、SystemExit
和KeyboardInterrupt
。看GeneratorExit
try:
someFunction()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print message
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
File "exc.py", line 7, in <module>
raise CustomException("hi")
CustomException: hi
如果要深入挖掘并检查堆栈、查看变量等,请在except块内使用pdb
模块的函数:
import pdb
pdb.post_mortem()
我发现最后一个方法在查找bug时非常有用。获取异常对象所属类的名称:
e.__class__.__name__
使用print_exc()函数还将打印堆栈跟踪,这是任何错误消息的基本信息
像这样:
from traceback import print_exc
class CustomException(Exception): pass
try:
raise CustomException("hi")
except Exception, e:
print 'type is:', e.__class__.__name__
print_exc()
# print "exception happened!"
您将得到如下输出:
try:
someFunction()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
print message
import logging
log = logging.getLogger()
log.exception("Message for you, sir!")
type is: CustomException
Traceback (most recent call last):
File "exc.py", line 7, in <module>
raise CustomException("hi")
CustomException: hi
输出:
special case of CustomException not interfering
special case of CustomException not interfering
Traceback (most recent call last):
File "test.py", line 13, in <module>
raise CustomException(e.message)
__main__.CustomException: hi
和解释器打印异常:
Traceback (most recent call last):
File "test.py", line 9, in <module>
calculate()
File "test.py", line 6, in calculate
raise CustomException("hi")
__main__.CustomException: hi
输出:
special case of CustomException not interfering
special case of CustomException not interfering
Traceback (most recent call last):
File "test.py", line 13, in <module>
raise CustomException(e.message)
__main__.CustomException: hi
CustomException不干扰的特殊情况
回溯(最近一次呼叫最后一次):
文件“test.py”,第13行,在
引发自定义异常(e.message)
__主\自定义异常:嗨
请注意,回溯如何不包括
calculate()
第9行的函数,这是原始异常的起源e
只要避免捕获异常,Python打印的回溯将告诉您发生了什么异常。除非somefunction
是一个非常糟糕的编码遗留函数,否则您不需要您所要求的
class general_function_handler(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
return self.__class__(self.func.__get__(obj, type))
def __call__(self, *args, **kwargs):
try:
retval = self.func(*args, **kwargs)
except Exception, e :
logging.warning('Exception in %s' % self.func)
template = "An exception of type {0} occured. Arguments:\n{1!r}"
message = template.format(type(e).__name__, e.args)
logging.exception(message)
sys.exit(1) # exit on all exceptions for now
return retval
使用多个except
子句以不同的方式处理不同的异常:
try:
someFunction()
except ValueError:
# do something
except ZeroDivision:
# do something else
主要的一点是,您不应该捕获泛型异常,而应该只捕获需要捕获的异常。我确信您不想隐藏意外的错误或bug。在Python 2中,以下内容非常有用
except Exception, exc:
# This is how you get the type
excType = exc.__class__.__name__
# Here we are printing out information about the Exception
print 'exception type', excType
print 'exception msg', str(exc)
# It's easy to reraise an exception with more information added to it
msg = 'there was a problem with someFunction'
raise Exception(msg + 'because of %s: %s' % (excType, exc))
为了补充Lauritz的答案,我创建了一个用于异常处理的装饰器/包装器,包装器记录发生的异常类型
class general_function_handler(object):
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
return self.__class__(self.func.__get__(obj, type))
def __call__(self, *args, **kwargs):
try:
retval = self.func(*args, **kwargs)
except Exception, e :
logging.warning('Exception in %s' % self.func)
template = "An exception of type {0} occured. Arguments:\n{1!r}"
message = template.format(type(e).__name__, e.args)
logging.exception(message)
sys.exit(1) # exit on all exceptions for now
return retval
这可以通过decorator在类方法或独立函数上调用:
@通用函数处理程序
有关完整示例,请参阅我的博客:您的问题是:“如何准确地看到导致异常发生的someFunction()中发生了什么?”
在我看来,您并不是在问如何处理生产代码中不可预见的异常(正如许多答案所假设的那样),而是在开发过程中如何找出导致特定异常的原因
最简单的方法是使用一个调试器,它可以在发生未捕获异常时停止,最好不要退出,以便您可以检查变量。例如,Eclipse开源IDE中的PyDev可以做到这一点。要在Eclipse中启用该功能,请打开Debug透视图,在
运行菜单中选择管理Python异常断点
,然后选中在未捕获异常时暂停
,您可以按照Lauritz的建议启动,包括:
except Exception as ex:
然后只需打印ex
,如下所示:
try:
#your try code here
except Exception as ex:
print ex
下面是我如何处理我的异常。我们的想法是尝试解决这个问题,如果这很容易,然后添加一个更理想的解决方案,如果可能的话。不要解决生成异常的代码中的问题,否则代码会丢失对原始算法的跟踪,而原始算法应该被写到点子上。但是,传递解决问题所需的数据,并返回lambda,以防在生成问题的代码之外无法解决问题
path = 'app.p'
def load():
if os.path.exists(path):
try:
with open(path, 'rb') as file:
data = file.read()
inst = pickle.load(data)
except Exception as e:
inst = solve(e, 'load app data', easy=lambda: App(), path=path)()
else:
inst = App()
inst.loadWidgets()
# e.g. A solver could search for app data if desc='load app data'
def solve(e, during, easy, **kwargs):
class_name = e.__class__.__name__
print(class_name + ': ' + str(e))
print('\t during: ' + during)
return easy
现在,因为我不想与我的应用程序的目的相左