python:我怎么知道发生了什么types的exception?
我有一个主程序调用的函数:
try: someFunction() except: print "exception happened!"
但是在函数执行过程中引发exception,所以跳到了except
部分except
。
我怎样才能看到someFunction()
中发生了什么事情,导致exception发生?
其他的答案都指出,你不应该看到一般的例外,但似乎没有人想告诉你为什么,这是理解什么时候可以打破“规则”的关键。 这是一个解释。 基本上,这样就不会隐藏:
- 发生错误的事实
- 发生错误的具体细节( 错误隐藏反模式 )
所以只要你照顾不要做这些事情,可以赶上一般的例外。 例如,您可以以另一种方式向用户提供有关exception的信息,如:
- 在GUI中作为对话呈现exception
- 将工作线程或进程中的exception转移到multithreading或多处理应用程序中的控制线程或进程
那么如何捕捉genericsexception? 有几种方法。 如果你只是想要exception对象,像这样做:
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
确保 message
以难以想象的方式引起用户的注意! 如上所示,打印它可能是不够的,如果消息埋在许多其他消息。 如果没有得到用户的关注,就等于吞噬了所有的例外,如果有一个印象,在阅读本页上的答案之后应该已经走了,这不是一件好事 。 用raise
语句结束except块将通过透明地重新调整被捕获的exception来解决问题。
上面和使用的区别只是except:
没有任何争论是双重的:
- 裸露
except:
不给你exception对象检查 -
SystemExit
,KeyboardInterrupt
和GeneratorExit
exception没有被上面的代码捕获,这通常是你想要的。 查看exception层次结构 。
如果你还想得到相同的堆栈跟踪,如果你没有捕获exception,你可以像这样(仍在except子句中):
import traceback print traceback.format_exc()
如果使用logging
模块,则可以将日志打印到日志(以及消息),如下所示:
import logging log = logging.getLogger() log.exception("Message for you, sir!")
如果您想深入了解堆栈并查看variables,请在except块中使用pdb
模块的post_mortem
函数:
import pdb pdb.post_mortem()
我发现这个最后的方法在寻找错误的时候是无价的。
获取exception对象所属类的名称:
e.__class__.__name__
并使用print_exc()函数也将打印堆栈跟踪,这是任何错误消息的重要信息。
喜欢这个:
from traceback import print_exc class dazhuangcao(Exception): pass try: raise dazhuangcao("hi") except Exception, e: print 'type is:', e.__class__.__name__ print_exc() # print "exception happened!"
你会得到这样的输出:
type is: dazhuangcao Traceback (most recent call last): File "exc.py", line 7, in <module> raise dazhuangcao("hi") dazhuangcao: hi
你通常不应该try: ... except
所有可能的例外try: ... except
这是过分宽泛的。 只要赶上那些预计会出于任何原因发生的事情。 如果你真的必须,例如,如果你想在debugging的时候发现更多的问题,你应该这样做
try: ... except Exception as ex: print ex # do whatever you want for debugging. raise # re-raise exception.
除非somefunction
是一个非常糟糕的编码遗留函数,否则你不应该需要你所要求的。
使用多个except
从句以不同的方式处理不同的例外:
try: someFunction() except ValueError: # do something except ZeroDivision: # do something else
重点是你不应该捕获genericsexception,但只有你需要的exception。 我敢肯定,你不想影响意外的错误或错误。
尝试:someFunction()除了例外,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))
以下是我如何处理我的例外。 这个想法是如果这很容易就尝试解决这个问题,如果可能的话,稍后添加一个更理想的解决scheme。 不要在生成exception的代码中解决问题,否则代码会丢失原始algorithm的轨迹,该algorithm应该写入到点。 但是,传递需要的数据来解决问题,并返回一个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() # eg 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
就目前而言,由于我不想对我的应用程序的目的进行思考,所以我没有添加任何复杂的解决scheme。 但是在将来,当我对可能的解决scheme有更多的了解时(因为应用程序devise得更多),我可以添加一个由during
索引的解决scheme字典。
在所示的示例中,一种解决scheme可能是查找其他地方存储的应用程序数据,也就是说如果“app.p”文件被误删除了。
就目前而言,由于编写exception处理程序并不是一个聪明的想法(我们还不知道解决这个问题的最佳方法,因为应用程序devise将会发展),我们只需返回一个简单的修复程序,就像我们正在运行该应用程序的第一次(在这种情况下)。
实际的exception可以通过以下方式捕获:
try: i = 1/0 except Exception as e: print e
您可以从Python教程中了解有关exception的更多信息。
为了增加Lauritz的答案,我创build了一个装饰器/包装器来处理exception,并且包装器logging了发生了哪种types的exception。
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
这可以通过装饰器在类方法或独立函数上调用:
@general_function_handler
有关完整示例,请参阅我的博客: http : //ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/
你的问题是:“我怎么才能看到someFunction()中发生了什么事情,导致exception发生?
在我看来,你并没有问如何处理生产代码中不可预见的exception(尽可能多的答案),而是如何在开发过程中找出是什么导致了一个特殊的exception。
最简单的方法是使用一个debugging器,可以停止发生未捕获的exception,最好不要退出,以便检查variables。 例如,Eclipse开源IDE中的PyDev可以做到这一点。 要在Eclipse中启用该function,请打开Debug透视图,在Run
菜单中selectManage Python Exception Breakpoints
,然后选中Suspend on uncaught exceptions
。
你可以从Lauritz推荐的开始,用:
except Exception as ex:
然后只是像这样print ex
:
try: #your try code here except Exception as ex: print ex
只要避免捕获exception,Python打印的追踪将告诉你发生了什么exception。