简体   繁体   English

Python - 有条件地捕获异常

[英]Python - Conditionally Catching Exceptions

Is it possible to conditionally catch exceptions in python?是否可以在python中有条件地捕获异常? I would like to be able to write a function so that the caller can decide who handles the exception.我希望能够编写一个函数,以便调用者可以决定谁来处理异常。

Basically, I would like something like this:基本上,我想要这样的东西:

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"

I know I could write some kludgy code that does what I want, but I want a pythonic answer if there is one.我知道我可以编写一些我想要的笨拙的代码,但是如果有的话,我想要一个 Pythonic 的答案。
Thanks.谢谢。

You can re-raise the exception if you don't want to handle it:如果您不想处理它,您可以重新引发异常:

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"

Another option is to create your own exceptions that subclass Exception (or a specific exception like urllib2.HTTPError ) and then only catch/throw ( raise ) your custom 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

The question just doesn't have enough answers ;-)这个问题没有足够的答案;-)

Here's one more for the record books.这是记录簿的另一本。 Just create a dummy exception:只需创建一个虚拟异常:

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

Then, use a conditional expression to decide whether to match the real exception or the placeholder exception (which never gets raised):然后,使用条件表达式来决定是匹配真正的异常还是占位符异常(永远不会引发):

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

You can use:您可以使用:

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

The exception type can be a variable.异常类型可以是变量。

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

Obfuscated Python ("Pythonic"?) version:混淆的 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";

Works without the parentheses, actually, but as long as we're being obfuscated let's not confuse people with little known rules like precedence for except statements.实际上,没有括号也可以工作,但是只要我们被混淆了,就不要让人们混淆一些鲜为人知的规则,例如 except 语句的优先级。

You could always catch it and conditionally re-raise it like so:你总是可以抓住它并有条件地重新加注,如下所示:

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

Yes.是的。 I prefer positive conditions when it makes sense:当有意义时,我更喜欢积极的条件:

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

You have a two basic choices:您有两个基本选择:

  1. Treat handle_exceptions as a boolean, and re-raise if Falsehandle_exceptions视为布尔值,如果为False ,则重新引发
  2. Treat handle_exceptions as the exceptions to handlehandle_exceptions视为要处理的异常

Along the boolean route you have two basic choices:沿着布尔路线,您有两个基本选择:

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"

or要么

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"

Along the 'treat handle_exceptions as the exceptions to handle' route you can do this:沿着“将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"

and you would call it like so:你会这样称呼它:

my_func(some_arg, ValueError)  # to handle ValueErrors

or要么

my_func(some_arg)  # to not handle any exeptions

This has the advantage/disadvantage of the caller being able to specify which exceptions are handled.这具有调用者能够指定处理哪些异常的优点/缺点。 If you do take this last route you might also want to specify an exception handler, perhaps something like this:如果您确实采用了最后一条路线,您可能还想指定一个异常处理程序,可能是这样的:

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

A nice looking technique to improve on the other answers is to wrap the conditional exception handling logic in a context manager that can be reused, like this:改进其他答案的一个漂亮技术是将条件异常处理逻辑包装在可以重用的上下文管理器中,如下所示:

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 

Then, in your code, you can say:然后,在您的代码中,您可以说:

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