4.3. Exceptions
Exceptions are a means of breaking out of the normal flow of control of a code block in order to handle errors or other exceptional
异常是为了处理错误和其他异常情况的一种手段
conditions. An exception is raised at the point where the error is detected; it may be handled by the surrounding code block or by any code block that directly or indirectly invoked the code block where the error occurred.
The Python interpreter raises an exception when it detects a run-time error (such as division by zero). A Python program can also explicitly raise an exception with the raise
statement. Exception handlers are specified with the try
... except
statement. The finally
clause of such a statement can be used to specify cleanup code which does not handle the exception, but is executed whether an exception occurred or not in the preceding code.
异常的产生
1.python解释器检测到运行时错误时会产生一个异常
2.也可以使用raise语句显示引发一个异常
异常处理程序
1.由try语句指定
Python uses the “termination” model of error handling: an exception handler can find out what happened and continue execution at an outer level, but it cannot repair the cause of the error and retry the failing operation (except by re-entering the offending piece of code from the top).
When an exception is not handled at all, the interpreter terminates execution of the program, or returns to its interactive main loop. In either case, it prints a stack backtrace, except when the exception is SystemExit
.
当异常没有被处理
1.解释器会终止程序的执行
2.返回到解释器的交互主循环
Exceptions are identified by class instances. The except
clause is selected depending on the class of the instance: it must reference the class of the instance or a base class thereof. The instance can be received by the handler and can carry additional information about the exceptional condition.
异常由类的实例标识,except子句的选择依赖于类的实例: 必须引用实例的类或该类的基类.
实例可以被处理程序接收,并且可以携带关于异常的附加信息
Note
Exception messages are not part of the Python API. Their contents may change from one version of Python to the next without warning and should not be relied on by code which will run under multiple versions of the interpreter.
7.8. The raise
statement
raise_stmt ::= "raise" [expression
["from"expression
]]
If no expressions are present, raise
re-raises the last exception that was active in the current scope. If no exception is active in the current scope, a RuntimeError
exception is raised indicating that this is an error.
如果raise后没有expression,会重新引发当前范围内最后激发的异常.如果当前范围没有异常被激活,会产生一个运行时错误异常以表明这是一个错误
Otherwise, raise
evaluates the first expression as the exception object. It must be either a subclass or an instance of BaseException
. If it is a class, the exception instance will be obtained when needed by instantiating the class with no arguments.
另一方面,raise评估第一个表达式作为异常对象,该表达式必须是BaseException的子类或者实例.如果是一个类,可以通过实例化该类获得异常实例对象
The type of the exception is the exception instance’s class, the value is the instance itself.
异常的类型是异常的类类型,异常的值是异常实例对象本身
A traceback object is normally created automatically when an exception is raised and attached to it as the __traceback__
attribute,
当引发异常时会自动创建一个traceback对象(代表异常的堆栈跟踪),并且以__traceback__属性的形式附加到该异常实例对象
which is writable. You can create an exception and set your own traceback in one step using the with_traceback()
exception
该属性可写,可以使用with_traceback()异常函数设置异常的traceback
method (which returns the same exception instance, with its traceback set to its argument), like so:
返回值是设置traceback到其参数的同一个异常实例对象
raise Exception("foo occurred").with_traceback(tracebackobj)
The from
clause is used for exception chaining: if given, the second expression must be another exception class or instance,
from子句用于异常链接: 第二个参数必须是另一个异常类或异常实例对象
which will then be attached to the raised exception as the __cause__
attribute (which is writable). If the raised exception is not handled, both exceptions will be printed:
被链接的异常会以__cause__属性的形式附加到当前异常实例对象,如果raise出的异常没有处理,当前异常和链接的异常都会被打印
>>> try:
... print(1 / 0)
... except Exception as exc:
... raise RuntimeError("Something bad happened") from exc
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
A similar mechanism works implicitly if an exception is raised inside an exception handler or a finally
clause: the previous
exception is then attached as the new exception’s __context__
attribute:
在异常处理程序或在finally子句中产生的异常有一个和from相似的隐式机制: 前一个异常会以__context__属性的形式附加到新的异常实例对象
>>> try:
... print(1 / 0)
... except:
... raise RuntimeError("Something bad happened")
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: int division or modulo by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
RuntimeError: Something bad happened
Additional information on exceptions can be found in section Exceptions, and information about handling exceptions is in section The try statement.
8.4. The try
statement
The try
statement specifies exception handlers and/or cleanup code for a group of statements:
try语句指定异常处理程序,和/或一组语句的代码
try_stmt ::= try1_stmt | try2_stmt try1_stmt ::= "try" ":"suite
("except" [expression
["as"identifier
]] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try2_stmt ::= "try" ":"suite
"finally" ":"suite
The except
clause(s) specify one or more exception handlers. When no exception occurs in the try
clause, no exception handler
except子句指定一个或多个异常处理程序.如果try子句中没有异常发生,没有异常处理程序被执行
is executed. When an exception occurs in the try
suite, a search for an exception handler is started. This search inspects the
当try套件中出现一个异常,就会启动搜索异常处理程序
except clauses in turn until one is found that matches the exception. An expression-less except clause, if present, must be last; it
该搜索依次检查每一个except子句,知道找到匹配该exception子句的except子句.匹配任何异常的except子句必须在最后
matches any exception. For an except clause with an expression, that expression is evaluated, and the clause matches the
exception if the resulting object is “compatible” with the exception.
带有表达式的except子句,表达式会被评估,如果结果对象和该异常兼容那么会匹配该except子句.
An object is compatible with an exception if it is the class or a base class of the exception object or a tuple containing an item compatible with the exception.
一个对象和一个异常兼容,如果该对象是异常对象类或基类,或者包含兼容该异常的项目的元组
If no except clause matches the exception, the search for an exception handler continues in the surrounding code and on the invocation stack. [1]
[1](
|
如果没有except子句和该异常匹配,对异常处理程序的搜索会继续在包围代码块和调用堆栈中搜索
If the evaluation of an expression in the header of an except clause raises an exception, the original search for a handler is canceled and a search starts for the new exception in the surrounding code and on the call stack (it is treated as if the entire try
statement raised the exception).
如果评估except子句中的表达式引发一个异常,原来对异常处理程序的搜索将会被取消,并开始在围绕代码和调用堆栈中搜索新异常的搜索(该异常当做是整个try语句产生的异常)
When a matching except clause is found, the exception is assigned to the target specified after the as
keyword in that except
当搜索到匹配的except子句,异常会被赋值给as后的目标参数,并且该except子句套件会被执行
clause, if present, and the except clause’s suite is executed. All except clauses must have an executable block. When the end of
所有的except子句必须有一个可执行代码块,当执行到该代码块的结尾,
this block is reached, execution continues normally after the entire try statement. (This means that if two nested handlers exist for
会继续执行tyr之后的语句(这意味着,处理同一个异常的异常处理程序存在嵌套关系的话,如果内层异常处理程序处理了该异常,那么外层异常处理程序,不会再执行)
the same exception, and the exception occurs in the try clause of the inner handler, the outer handler will not handle the exception.)
When an exception has been assigned using as target
, it is cleared at the end of the except clause. This is as if
赋值给as后target参数的异常会在该except子句执行结束时被清除
except E as N:
foo
was translated to
except E as N:
try:
foo
finally:
del N
This means the exception must be assigned to a different name to be able to refer to it after the except clause.
者意味着,异常必须赋值给不同名称,保证except子句结束后可以访问
Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
异常会被清除,因为异常实例附加有traceback(traceback object以__traceback__属性的形式附加到异常实例对象),这会形成堆栈框架上的循环引用,保持堆栈框架中的所有局部变量生存,知道下一次垃圾回收出现
Before an except clause’s suite is executed, details about the exception are stored in the sys
module and can be accessed
except子句套件执行前,异常的详细信息保存在sys模块中,可以通过sys.exc_info()函数访问
via sys.exc_info()
. sys.exc_info()
returns a 3-tuple consisting of the exception class, the exception instance and a traceback
sys.exc_info()函数返回一个由异常实例对象对应的类, 异常实例对象, 和traceback object构成的元组,标识程序中异常的发生点
object (see section The standard type hierarchy) identifying the point in the program where the exception occurred. sys.exc_info()
values are restored to their previous values (before the call) when returning from a function that handled an exception.
当从处理异常的函数中返回,sys.exc_info()的值会恢复到之前的值(被调用之前)
The optional else
clause is executed if and when control flows off the end of the try
clause. [2] Exceptions in the else
clause are not handled by the preceding except
clauses.
[2]( Currently, control “flows off the end” except in the case of an exception or the execution of a return , continue ,or break statement.) |
If finally
is present, it specifies a ‘cleanup’ handler. The try
clause is executed, including any except
and else
clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally
clause is executed. If
try, except, else,子句中的异常如果没有被处理,会被暂时保存.在执行finally子句时,如果存在暂存的异常,会在finally子句的结尾被重新引发.如果finally子句引发新的异常,原来暂存的异常会以__context__属性的形式附加到该异常实例对象.如果finally
there is a saved exception it is re-raised at the end of the finally
clause. If the finally
clause raises another exception, the saved exception is set as the context of the new exception. If the finally
clause executes a return
or break
statement, the saved exception is discarded:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
The exception information is not available to the program during execution of the finally
clause.
When a return
, break
or continue
statement is executed in the try
suite of a try
...finally
statement, the finally
clause is also executed ‘on the way out.’ A continue
statement is illegal in the finally
clause. (The reason is a problem with the current implementation — this restriction may be lifted in the future).
The return value of a function is determined by the last return
statement executed. Since the finally
clause always executes, a return
statement executed in the finally
clause will always be the last one executed:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
Additional information on exceptions can be found in section Exceptions, and information on using the raise
statement to generate exceptions may be found in section The raise statement.