繁体   English   中英

Python - 有条件地捕获异常

[英]Python - Conditionally Catching Exceptions

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

基本上,我想要这样的东西:

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

我知道我可以编写一些我想要的笨拙的代码,但是如果有的话,我想要一个 Pythonic 的答案。
谢谢。

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

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

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

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

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'

您可以使用:

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";

异常类型可以是变量。

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";

实际上,没有括号也可以工作,但是只要我们被混淆了,就不要让人们混淆一些鲜为人知的规则,例如 except 语句的优先级。

你总是可以抓住它并有条件地重新加注,如下所示:

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

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

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

您有两个基本选择:

  1. handle_exceptions视为布尔值,如果为False ,则重新引发
  2. handle_exceptions视为要处理的异常

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

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()

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

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... 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM