在一行中捕获多个异常(块除外)

问题:在一行中捕获多个异常(块除外)

我知道我可以做到:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

我也可以这样做:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

但是,如果我想在两个不同的异常中做同样的事情,那么我现在想到的最好的方法就是:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

有什么办法可以做这样的事情(因为在两种情况下都要采取的行动是say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

现在,这确实不起作用,因为它与以下语法匹配:

try:
    # do something that may fail
except Exception, e:
    # say please

因此,我捕捉两个截然不同的异常的努力并未完全实现。

有没有办法做到这一点?

I know that I can do:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

I can also do this:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

But if I want to do the same thing inside two different exceptions, the best I can think of right now is to do this:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

Is there any way that I can do something like this (since the action to take in both exceptions is to say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

Now this really won’t work, as it matches the syntax for:

try:
    # do something that may fail
except Exception, e:
    # say please

So, my effort to catch the two distinct exceptions doesn’t exactly come through.

Is there a way to do this?


回答 0

Python文档

例如,except子句可以将多个异常命名为带括号的元组。

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

或者,仅对于Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

用逗号将变量与变量分开仍然可以在Python 2.6和2.7中使用,但是现在已弃用,并且在Python 3中不起作用。现在您应该使用as

From Python Documentation:

An except clause may name multiple exceptions as a parenthesized tuple, for example

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Or, for Python 2 only:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Separating the exception from the variable with a comma will still work in Python 2.6 and 2.7, but is now deprecated and does not work in Python 3; now you should be using as.


回答 1

如何在一行中捕获多个异常(块除外)

做这个:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

由于使用了逗号将错误对象分配给名称的较旧语法,因此需要使用括号。该as关键字用于分配。您可以为错误对象使用任何名称,我error个人更喜欢。

最佳实践

要以当前方式并与Python向前兼容的方式执行此操作,您需要使用逗号分隔Exceptions,并用括号将其包裹起来,以区别于早期的语法,后者通过遵循用逗号。

这是一个简单用法的示例:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

我仅指定这些异常以避免隐藏错误,如果遇到错误,我希望从中获得完整的堆栈跟踪。

此处记录:https : //docs.python.org/tutorial/errors.html

您可以将异常分配给变量,(e很常见,但是,如果您需要长时间的异常处理,或者您的IDE像我的一样,仅突出显示比这个更大的选择,那么您可能更喜欢使用更冗长的变量。)实例具有args属性。这是一个例子:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

请注意,在Python 3中,结束errexcept块时该对象不在范围内。

不推荐使用

您可能会看到用逗号分配错误的代码。不赞成使用此用法,它是Python 2.5及更早版本中唯一可用的形式,并且如果您希望代码与Python 3向前兼容,则应更新语法以使用新形式:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

如果在代码库中看到逗号名称分配,并且您正在使用Python 2.5或更高版本,请切换到新的方式来执行此操作,以便在升级时代码保持兼容。

suppress上下文管理器

可接受的答案实际上是最少4行代码:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

tryexceptpass线可以与单线处理抑制上下文管理器,可以在Python 3.4

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

因此,当您想pass在某些exceptions情况下使用suppress

How do I catch multiple exceptions in one line (except block)

Do this:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

The parentheses are required due to older syntax that used the commas to assign the error object to a name. The as keyword is used for the assignment. You can use any name for the error object, I prefer error personally.

Best Practice

To do this in a manner currently and forward compatible with Python, you need to separate the Exceptions with commas and wrap them with parentheses to differentiate from earlier syntax that assigned the exception instance to a variable name by following the Exception type to be caught with a comma.

Here’s an example of simple usage:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

I’m specifying only these exceptions to avoid hiding bugs, which if I encounter I expect the full stack trace from.

This is documented here: https://docs.python.org/tutorial/errors.html

You can assign the exception to a variable, (e is common, but you might prefer a more verbose variable if you have long exception handling or your IDE only highlights selections larger than that, as mine does.) The instance has an args attribute. Here is an example:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Note that in Python 3, the err object falls out of scope when the except block is concluded.

Deprecated

You may see code that assigns the error with a comma. This usage, the only form available in Python 2.5 and earlier, is deprecated, and if you wish your code to be forward compatible in Python 3, you should update the syntax to use the new form:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

If you see the comma name assignment in your codebase, and you’re using Python 2.5 or higher, switch to the new way of doing it so your code remains compatible when you upgrade.

The suppress context manager

The accepted answer is really 4 lines of code, minimum:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

The try, except, pass lines can be handled in a single line with the suppress context manager, available in Python 3.4:

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

So when you want to pass on certain exceptions, use suppress.


回答 2

Python文档-> 8.3处理异常

一条try语句可能具有多个except子句,以指定不同异常的处理程序。最多将执行一个处理程序。处理程序仅处理在相应的try子句中发生的异常,而不处理同一try语句的其他处理程序中的异常。exclude子句可以将多个异常命名为带括号的元组,例如:

except (RuntimeError, TypeError, NameError):
    pass

请注意,必须在该元组周围加上括号,因为除了ValueError, e:用于except ValueError as e:现代Python中通常编写的语法(如下所述)外,其他语法都是这样。为了向后兼容,仍旧支持旧语法。这意味着except RuntimeError, TypeError不等于 except (RuntimeError, TypeError):except RuntimeError as TypeError:不是您想要的。

From Python documentation -> 8.3 Handling Exceptions:

A try statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example:

except (RuntimeError, TypeError, NameError):
    pass

Note that the parentheses around this tuple are required, because except ValueError, e: was the syntax used for what is normally written as except ValueError as e: in modern Python (described below). The old syntax is still supported for backwards compatibility. This means except RuntimeError, TypeError is not equivalent to except (RuntimeError, TypeError): but to except RuntimeError as TypeError: which is not what you want.


回答 3

如果您经常使用大量异常,则可以预定义一个元组,因此不必多次重新键入它们。

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

笔记:

  1. 如果您还需要捕获除预定义元组中的异常以外的其他异常,则需要定义另一个except块。

  2. 如果您不能忍受全局变量,请在main()中定义它,并在需要的地方传递它…

If you frequently use a large number of exceptions, you can pre-define a tuple, so you don’t have to re-type them many times.

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

NOTES:

  1. If you, also, need to catch other exceptions than those in the pre-defined tuple, you will need to define another except block.

  2. If you just cannot tolerate a global variable, define it in main() and pass it around where needed…


回答 4

一种方法是..

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

另一种方法是创建一种方法,该方法执行由except块执行的任务,并在except您编写的所有块中调用它。

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

我知道第二种方法并不是做到这一点的最佳方法,但我只是在说明一些实现此目的的方法。

One of the way to do this is..

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

and another way is to create method which performs task executed by except block and call it through all of the except block that you write..

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

I know that second one is not the best way to do this, but i’m just showing number of ways to do this thing.