Skip to content

Commit 011909f

Browse files
committed
14.8小节完成
1 parent 0932a48 commit 011909f

File tree

1 file changed

+82
-80
lines changed

1 file changed

+82
-80
lines changed

source/c14/p08_creating_custom_exceptions.rst

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,105 +5,107 @@
55
----------
66
问题
77
----------
8-
You’re building an application and would like to wrap lower-level exceptions with cus‐
9-
tom ones that have more meaning in the context of your application.
8+
在你构建的应用程序中,你想将底层异常包装成自定义的异常。
109

1110
|
1211
1312
----------
1413
解决方案
1514
----------
16-
Creating new exceptions is easy—just define them as classes that inherit from Excep
17-
tion (or one of the other existing exception types if it makes more sense). For example,
18-
if you are writing code related to network programming, you might define some custom
19-
exceptions like this:
15+
创建新的异常很简单——定义新的类,让它继承自 ``Exception`` (或者是任何一个已存在的异常类型)。
16+
例如,如果你编写网络相关的程序,你可能会定义一些类似如下的异常:
2017

21-
class NetworkError(Exception):
22-
pass
18+
.. code-block:: python
2319
24-
class HostnameError(NetworkError):
25-
pass
20+
class NetworkError(Exception):
21+
pass
2622
27-
class TimeoutError(NetworkError):
28-
pass
23+
class HostnameError(NetworkError):
24+
pass
2925
30-
class ProtocolError(NetworkError):
31-
pass
26+
class TimeoutError(NetworkError):
27+
pass
3228
33-
Users could then use these exceptions in the normal way. For example:
29+
class ProtocolError(NetworkError):
30+
pass
3431
35-
try:
36-
msg = s.recv()
37-
except TimeoutError as e:
38-
...
39-
except ProtocolError as e:
40-
...
32+
然后用户就可以像通常那样使用这些异常了,例如:
33+
34+
.. code-block:: python
35+
36+
try:
37+
msg = s.recv()
38+
except TimeoutError as e:
39+
...
40+
except ProtocolError as e:
41+
...
4142
4243
|
4344
4445
----------
4546
讨论
4647
----------
47-
Custom exception classes should almost always inherit from the built-in Exception
48-
class, or inherit from some locally defined base exception that itself inherits from Ex
49-
ception. Although all exceptions also derive from BaseException, you should not use
50-
this as a base class for new exceptions. BaseException is reserved for system-exiting
51-
exceptions, such as KeyboardInterrupt or SystemExit, and other exceptions that
52-
should signal the application to exit. Therefore, catching these exceptions is not the
53-
54-
intended use case. Assuming you follow this convention, it follows that inheriting from
55-
BaseException causes your custom exceptions to not be caught and to signal an im‐
56-
minent application shutdown!
57-
Having custom exceptions in your application and using them as shown makes your
58-
application code tell a more coherent story to whoever may need to read the code. One
59-
design consideration involves the grouping of custom exceptions via inheritance. In
60-
complicated applications, it may make sense to introduce further base classes that group
61-
different classes of exceptions together. This gives the user a choice of catching a nar‐
62-
rowly specified error, such as this:
63-
64-
try:
65-
s.send(msg)
66-
except ProtocolError:
48+
自定义异常类应该总是继承自内置的 ``Exception`` 类,
49+
或者是继承自那些本身就是从 ``Exception`` 继承而来的类。
50+
尽管所有类同时也继承自 ``BaseException`` ,但你不应该使用这个基类来定义新的异常。
51+
``BaseException`` 是为系统退出异常而保留的,比如 ``KeyboardInterrupt`` 或 ``SystemExit``
52+
以及其他那些会给应用发送信号而退出的异常。
53+
因此,捕获这些异常本身没什么意义。
54+
这样的话,假如你继承 ``BaseException``
55+
可能会导致你的自定义异常不会被捕获而直接发送信号退出程序运行。
56+
57+
在程序中引入自定义异常可以使得你的代码更具可读性,能清晰显示谁应该阅读这个代码。
58+
还有一种设计是将自定义异常通过继承组合起来。在复杂应用程序中,
59+
使用基类来分组各种异常类也是很有用的。它可以让用户捕获一个范围很窄的特定异常,比如下面这样的:
60+
61+
.. code-block:: python
62+
63+
try:
64+
s.send(msg)
65+
except ProtocolError:
66+
...
67+
68+
你还能捕获更大范围的异常,就像下面这样:
69+
70+
.. code-block:: python
71+
72+
try:
73+
s.send(msg)
74+
except NetworkError:
75+
...
76+
77+
如果你想定义的新异常重写了 ``__init__()`` 方法,
78+
确保你使用所有参数调用 ``Exception.__init__()`` ,例如:
79+
80+
.. code-block:: python
81+
82+
class CustomError(Exception):
83+
def __init__(self, message, status):
84+
super().__init__(message, status)
85+
self.message = message
86+
self.status = status
87+
88+
看上去有点奇怪,不过Exception的默认行为是接受所有传递的参数并将它们以元组形式存储在 ``.args`` 属性中.
89+
很多其他函数库和部分Python库默认所有异常都必须有 ``.args`` 属性,
90+
因此如果你忽略了这一步,你会发现有些时候你定义的新异常不会按照期望运行。
91+
为了演示 ``.args`` 的使用,考虑下下面这个使用内置的 `RuntimeError`` 异常的交互会话,
92+
注意看raise语句中使用的参数个数是怎样的:
93+
94+
::
95+
96+
>>> try:
97+
... raise RuntimeError('It failed')
98+
... except RuntimeError as e:
99+
... print(e.args)
67100
...
101+
('It failed',)
102+
>>> try:
103+
... raise RuntimeError('It failed', 42, 'spam')
104+
... except RuntimeError as e:
68105

69-
It also gives the ability to catch a broad range of errors, such as the following:
70-
71-
try:
72-
s.send(msg)
73-
except NetworkError:
106+
... print(e.args)
74107
...
108+
('It failed', 42, 'spam')
109+
>>>
75110

76-
If you are going to define a new exception that overrides the __init__() method of
77-
Exception, make sure you always call Exception.__init__() with all of the passed
78-
arguments. For example:
79-
80-
class CustomError(Exception):
81-
def __init__(self, message, status):
82-
super().__init__(message, status)
83-
self.message = message
84-
self.status = status
85-
86-
This might look a little weird, but the default behavior of Exception is to accept all
87-
arguments passed and to store them in the .args attribute as a tuple. Various other
88-
libraries and parts of Python expect all exceptions to have the .args attribute, so if you
89-
skip this step, you might find that your new exception doesn’t behave quite right in
90-
certain contexts. To illustrate the use of .args, consider this interactive session with the
91-
built-in RuntimeError exception, and notice how any number of arguments can be used
92-
with the raise statement:
93-
94-
>>> try:
95-
... raise RuntimeError('It failed')
96-
... except RuntimeError as e:
97-
... print(e.args)
98-
...
99-
('It failed',)
100-
>>> try:
101-
... raise RuntimeError('It failed', 42, 'spam')
102-
... except RuntimeError as e:
103-
104-
... print(e.args)
105-
...
106-
('It failed', 42, 'spam')
107-
>>>
108-
109-
For more information on creating your own exceptions, see the Python documentation.
111+
关于创建自定义异常的更多信息,请参考`Python官方文档 <https://docs.python.org/3/tutorial/errors.html>`_

0 commit comments

Comments
 (0)