Python - 有条理地捕获异常

时间:2011-11-16 03:41:48

标签: exception exception-handling python

是否有可能在python中有条件地捕获异常?我希望能够编写一个函数,以便调用者可以决定谁处理异常。

基本上,我想要这样的事情:

def my_func(my_arg, handle_exceptions):
    try:
        do_something(my_arg)
    except Exception, e if handle_exceptions:
        print "my_func is handling the exception"

我知道我可以写一些符合我想要的kludgy代码,但如果有的话,我想要一个pythonic答案。
感谢。

8 个答案:

答案 0 :(得分:22)

如果您不想处理异常,可以重新引发异常:

def my_func(my_arg, handle_exceptions):
    try:
        do_something(my_arg)
    except Exception, e:
        if not handle_exceptions:
            # preserve prior stack trace
            raise

            # Or, if you dont care about the stack prior to this point
            #raise Exception(e)

            # similarly, you can just re-raise e.  The stack trace will start here though.
            #raise e
        else:
            print "my_func is handling the exception"

另一种选择是创建自己的子类Exception(或urllib2.HTTPError之类的特定异常),然后只捕获/抛出(raise)自定义异常:

class MyException(Exception):
    def __init__(self, message):
        self.message = message

class MyExceptionTwo(Exception):
    def __init__(self, message):
        self.message = message
    def __repr__(self):
        return "Hi, I'm MyExceptionTwo.  My error message is: %s" % self.message

def something():
    if not tuesday:
        raise MyException("Error: it's not Tuesday.")
    else:
        raise MyExceptionTwo("Error: it's Tuesday.")

def my_func(my_arg):
    try:
        something()
    except MyException, e:
        print e.message
    # Will pass MyExceptionTwo up the call chain

def my_other_func():
    try:
        my_func(your_arg)
    except MyExceptionTwo, e:
        print str(e)
    # No need to catch MyException here since we know my_func() handles it
    # but we can hadle MyExceptionTwo here

答案 1 :(得分:14)

这个问题没有足够的答案; - )

这是记录簿的另外一个。只需创建一个虚拟异常:

class NeverMatch(Exception):
    'An exception class that is never raised by any code anywhere'

然后,使用条件表达式来决定是匹配真实异常还是占位符异常(永远不会引发):

try:
    do_something(my_arg)
except (Exception if handle_exceptions else NeverMatch) as e:
    print 'I am handling it'

答案 2 :(得分:5)

您可以使用:

def my_func(my_arg, handle_exceptions):
  try:
    do_something(my_arg);
  except Exception as e:
    if not handle_exceptions: raise
    print "my_func is handling the exception";

答案 3 :(得分:5)

异常类型可以是变量。

def my_func(my_arg, handle_exceptions):
  if handle_exceptions:
    exc_type = Exception
  else:
    exc_type = None

  try:
    do_something(my_arg);
  except exc_type, e:
    print "my_func is handling the exception";

混淆的Python(“Pythonic”?)版本:

def my_func(my_arg, handle_exceptions):
  try:
    do_something(my_arg);
  except (handle_exceptions and Exception), e:
    print "my_func is handling the exception";

实际上没有括号的情况下工作,但只要我们被混淆,就不要混淆人们那些鲜为人知的规则,比如除了陈述之外的优先权。

答案 4 :(得分:4)

你可以随时抓住它并有条件地重新加注它:

def my_func(my_arg, handle_exceptions):
  try:
    do_something(my_arg)
  except Exception:
    if handle_exceptions:
      print "my_func is handling the exception"
      #handle it
    else: 
      print "my_func is NOT handling the exception"
      raise

答案 5 :(得分:2)

是。当有意义时,我更喜欢积极的条件:

def my_func(my_arg, handle_exceptions):
  try:
    do_something(my_arg);
  except Exception, e:
    if handle_exceptions:
        print "my_func is handling the exception"
    else:
        raise

答案 6 :(得分:2)

您有两个基本选择:

  1. handle_exceptions视为布尔值,并在False
  2. 时重新加注
  3. handle_exceptions视为处理
  4. 的例外情况

    沿着布尔路线,您有两个基本选择:

    def my_func(my_arg, handle_exceptions):
        try:
            do_something(my_arg)
        except Exception, e:
            if not handle_exceptions:
                raise
            print "my_func is handling the exception"
    

    def my_func(my_arg, handle_exceptions):
        if handle_exceptions:
            exceptions = ValueError, IndexError # or whatever
        else:
            exceptions = NoExceptions # None in 2.x, or custom Exception class in 3.x
        try:
            do_something(my_arg)
        except exceptions, e:
            print "my_func is handling the exception"
    

    沿着'待遇handle_exceptions作为处理'路线的例外,你可以这样做:

    class NoExceptions(Exception):
        'Dummy exception, never raised'
    
    def my_func(my_arg, handle_exceptions=NoExceptions):
        try:
            do_something(my_arg)
        except handle_exceptions, e:
            print "my_func is handling the exception"
    

    你可以这样称呼它:

    my_func(some_arg, ValueError)  # to handle ValueErrors
    

    my_func(some_arg)  # to not handle any exeptions
    

    这有利于调用者能够指定处理哪些异常。如果您确实采用了最后一个路径,您可能还需要指定一个异常处理程序,可能是这样的:

    def my_func(my_arg, handle_exceptions=NoExceptions, handler=None):
        try:
            do_something(my_arg)
        except handle_exceptions, e:
            if handler is not None:
                handler(e)
            else:
                log_this_exception()
    

答案 7 :(得分:1)

改进其他答案的一个好看的技术是将条件异常处理逻辑包装在可以重用的上下文管理器中,如下所示:

from contextlib import contextmanager 

@contextmanager
def ignore_errors_if(exception_type, skip_condition): 
    try: 
        yield 
    except exception_type, excn: 
        if skip_condition: 
            logging.debug("SKIPPING EXCEPTION %s" % excn)  # etc... 
            pass 
        else: 
            raise excn 

然后,在您的代码中,您可以说:

def some_function(): 
    # ... 
    with ignore_errors_if(Exception, should_ignore_errors): 
        result = some_funciton_that_might_raise() 
    # Deal with result, although know that it might not be set...