forked from sixu05202004/pythontutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.html
More file actions
428 lines (397 loc) · 38.6 KB
/
errors.html
File metadata and controls
428 lines (397 loc) · 38.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>8. 错误和异常 — Python tutorial 2.7 documentation</title>
<link rel="stylesheet" href="_static/default.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.7',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="Python tutorial 2.7 documentation" href="index.html" />
<link rel="next" title="9. 类" href="classes.html" />
<link rel="prev" title="7. 输入和输出" href="inputoutput.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="classes.html" title="9. 类"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="inputoutput.html" title="7. 输入和输出"
accesskey="P">previous</a> |</li>
<li><a href="index.html">Python tutorial 2.7 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="tut-errors">
<span id="id1"></span><h1>8. 错误和异常<a class="headerlink" href="#tut-errors" title="Permalink to this headline">¶</a></h1>
<p>至今为止还没有进一步的谈论过错误信息,不过在你已经试验过的那些例子中,可能已经遇到过一些。Python 中(至少)有两种错误:语法错误和异常( <em>syntax errors</em> 和 <em>exceptions</em> )。</p>
<div class="section" id="tut-syntaxerrors">
<span id="id2"></span><h2>8.1. 语法错误<a class="headerlink" href="#tut-syntaxerrors" title="Permalink to this headline">¶</a></h2>
<p>语法错误,也被称作解析错误,也许是你学习 Python 过程中最常见抱怨:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">while</span> <span class="bp">True</span> <span class="k">print</span> <span class="s">'Hello world'</span>
<span class="go"> File "<stdin>", line 1, in ?</span>
<span class="go"> while True print 'Hello world'</span>
<span class="go"> ^</span>
<span class="go">SyntaxError: invalid syntax</span>
</pre></div>
</div>
<p>语法分析器指出错误行,并且在检测到错误的位置前面显示一个小“箭头”。 错误是由箭头 <em>前面</em> 的标记引起的(或者至少是这么检测的): 这个例子中,关键字 <tt class="xref std std-keyword docutils literal"><span class="pre">print</span></tt> 被发现存在错误,因为它前面少了一个冒号( <tt class="docutils literal"><span class="pre">':'</span></tt> )。 错误会输出文件名和行号,所以如果是从脚本输入的你就知道去哪里检查错误了。</p>
</div>
<div class="section" id="tut-exceptions">
<span id="id3"></span><h2>8.2. 异常<a class="headerlink" href="#tut-exceptions" title="Permalink to this headline">¶</a></h2>
<p>即使一条语句或表达式在语法上是正确的,当试图执行它时也可能会引发错误。 运行期检测到的错误称为 <em>异常</em> ,并且程序不会无条件的崩溃:很快,你将学到如何在 Python 程序中处理它们。 然而,大多数异常都不会被程序处理,像这里展示的一样最终会产生一个错误信息:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="mi">10</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">0</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">ZeroDivisionError</span>: <span class="n">int division or modulo by zero</span>
<span class="gp">>>> </span><span class="mi">4</span> <span class="o">+</span> <span class="n">spam</span><span class="o">*</span><span class="mi">3</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">NameError</span>: <span class="n">name 'spam' is not defined</span>
<span class="gp">>>> </span><span class="s">'2'</span> <span class="o">+</span> <span class="mi">2</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">TypeError</span>: <span class="n">Can't convert 'int' object to str implicitly</span>
</pre></div>
</div>
<p>错误信息的最后一行指出发生了什么错误。异常也有不同的类型,异常类型做为错误信息的一部分显示出来:示例中的异常分别为 零除错误( <tt class="xref py py-exc docutils literal"><span class="pre">ZeroDivisionError</span></tt> ) ,命名错误( <tt class="xref py py-exc docutils literal"><span class="pre">NameError</span></tt>) 和 类型 错误( <tt class="xref py py-exc docutils literal"><span class="pre">TypeError</span></tt> )。打印错误信息时,异常的类型作为异常的内置名显示。对于所有的内置异常都是如此,不过用户自定义异常就不一定了(尽管这是一个很有用的约定)。标准异常名是内置的标识(没有保留关键字)。</p>
<p>这一行后一部分是关于该异常类型的详细说明,这意味着它的内容依赖于异常类型。</p>
<p>错误信息的前半部分以堆栈的形式列出异常发生的位置。通常在堆栈中列出了源代码行,然而,来自标准输入的源码不会显示出来。</p>
<p><em class="xref std std-ref">bltin-exceptions</em> 列出了内置异常和它们的含义。</p>
</div>
<div class="section" id="tut-handling">
<span id="id4"></span><h2>8.3. 异常处理<a class="headerlink" href="#tut-handling" title="Permalink to this headline">¶</a></h2>
<p>通过编程处理选择的异常是可行的。 看一下下面的例子:它会一直要求用户输入,直到输入一个合法的整数为止,但允许用户终端这个程序(使用 <tt class="kbd docutils literal"><span class="pre">Control-C</span></tt> 或系统支持的任何方法)。 注意:用户产生的终端会引发一个 <tt class="xref py py-exc docutils literal"><span class="pre">KeyboardInterrupt</span></tt> 异常。</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">x</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="nb">raw_input</span><span class="p">(</span><span class="s">"Please enter a number: "</span><span class="p">))</span>
<span class="gp">... </span> <span class="k">break</span>
<span class="gp">... </span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">"Oops! That was no valid number. Try again..."</span>
<span class="gp">...</span>
</pre></div>
</div>
<p><tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句按如下方式工作。</p>
<ul class="simple">
<li>首先,执行 <em>try</em> 子句 (在 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 和 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 关键字之间的部分)。</li>
<li>如果没有异常发生, <em>except</em> 子句 在 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句执行完毕后就被忽略了。</li>
<li>如果在 try 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。如果异常匹配于 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 关键字后面指定的异常类型,就执行对应的except子句。然后继续执行 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句之后的代码。</li>
<li>如果发生了一个异常,在 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 子句中没有与之匹配的分支,它就会传递到上一级 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句中。如果最终仍找不到对应的处理语句,它就成为一个 <em>未处理异常</em> ,终止程序运行,显示提示信息。</li>
</ul>
<p>一个 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句可能包含多个 except 子句,分别指定处理不同的异常。至多只会有一个分支被执行。异常处理程序只会处理对应的 try 子句中发生的异常,在同一个 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句中,其他子句中发生的异常则不作处理。一个 except 子句可以在括号中列出多个异常的名字,例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="o">...</span> <span class="k">except</span> <span class="p">(</span><span class="ne">RuntimeError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">,</span> <span class="ne">NameError</span><span class="p">):</span>
<span class="o">...</span> <span class="k">pass</span>
</pre></div>
</div>
<p>最后一个 except 子句可以省略异常名称,以作为通配符使用。 你需要慎用此法,因为它会轻易隐藏一个实际的程序错误! 可以使用这种方法打印一条错误信息,然后重新抛出异常(允许调用者处理这个异常):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sys</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'myfile.txt'</span><span class="p">)</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
<span class="k">except</span> <span class="ne">IOError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"I/O error({0}): {1}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">errno</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">strerror</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"Could not convert data to an integer."</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"Unexpected error:"</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">raise</span>
</pre></div>
</div>
<p><tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> ... <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 语句可以带有一个 <em>else子句</em> ,该子句只能出现在所有 except 子句之后。当 try 语句没有抛出异常时,需要执行一些代码,可以使用这个子句。例如</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'cannot open'</span><span class="p">,</span> <span class="n">arg</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="n">arg</span><span class="p">,</span> <span class="s">'has'</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">readlines</span><span class="p">()),</span> <span class="s">'lines'</span>
<span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>使用 <tt class="xref std std-keyword docutils literal"><span class="pre">else</span></tt> 子句比在 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 子句中附加代码要好,因为这样可以避免 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> ... <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 意外的截获本来不属于它们保护的那些代码抛出的异常。</p>
<p>发生异常时,可能会有一个附属值,作为异常的 <em>参数</em> 存在。这个参数是否存在、是什么类型,依赖于异常的类型。</p>
<p>在异常名(列表)之后,也可以为 except 子句指定一个变量。这个变量绑定于一个异常实例,它存储在 <tt class="docutils literal"><span class="pre">instance.args</span></tt> 的参数中。为了方便起见,异常实例定义了 <tt class="xref py py-meth docutils literal"><span class="pre">__str__()</span></tt> ,这样就可以直接访问过打印参数而不必引用 <tt class="docutils literal"><span class="pre">.args</span></tt> 。 这种做法不受鼓励。相反,更好的做法是给异常传递一个参数(如果要传递多个参数,可以传递一个元组),把它绑定到 message 属性。一旦异常发生,它会在抛出前绑定所有指定的属性。</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s">'spam'</span><span class="p">,</span> <span class="s">'eggs'</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">inst</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="nb">type</span><span class="p">(</span><span class="n">inst</span><span class="p">)</span> <span class="c"># the exception instance</span>
<span class="gp">... </span> <span class="k">print</span> <span class="n">inst</span><span class="o">.</span><span class="n">args</span> <span class="c"># arguments stored in .args</span>
<span class="gp">... </span> <span class="k">print</span> <span class="n">inst</span> <span class="c"># __str__ allows args to be printed directly,</span>
<span class="gp">... </span> <span class="c"># but may be overridden in exception subclasses</span>
<span class="gp">... </span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">inst</span><span class="o">.</span><span class="n">args</span> <span class="c"># unpack args</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'x ='</span><span class="p">,</span> <span class="n">x</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'y ='</span><span class="p">,</span> <span class="n">y</span>
<span class="gp">...</span>
<span class="go"><class 'Exception'></span>
<span class="go">('spam', 'eggs')</span>
<span class="go">('spam', 'eggs')</span>
<span class="go">x = spam</span>
<span class="go">y = eggs</span>
</pre></div>
</div>
<p>对于那些未处理的异常,如果一个它们带有参数,那么就会被作为异常信息的最后部分(“详情”)打印出来。</p>
<p>异常处理器不仅仅处理那些在 try 子句中立刻发生的异常,也会处理那些 try 子句中调用的函数内部发生的异常。 例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">def</span> <span class="nf">this_fails</span><span class="p">():</span>
<span class="gp">... </span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">this_fails</span><span class="p">()</span>
<span class="gp">... </span><span class="k">except</span> <span class="ne">ZeroDivisionError</span> <span class="k">as</span> <span class="n">detail</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'Handling run-time error:'</span><span class="p">,</span> <span class="n">detail</span>
<span class="gp">...</span>
<span class="go">Handling run-time error: int division or modulo by zero</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-raising">
<span id="id5"></span><h2>8.4. 抛出异常<a class="headerlink" href="#tut-raising" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref std std-keyword docutils literal"><span class="pre">raise</span></tt> 语句允许程序员强制抛出一个指定的异常。例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">raise</span> <span class="ne">NameError</span><span class="p">(</span><span class="s">'HiThere'</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">NameError</span>: <span class="n">HiThere</span>
</pre></div>
</div>
<p>要抛出的异常由 <tt class="xref std std-keyword docutils literal"><span class="pre">raise</span></tt> 的唯一参数标识。它必需是一个异常实例或异常类(继承自 <tt class="xref py py-class docutils literal"><span class="pre">Exception</span></tt> 的类)。</p>
<p>如果你需要明确一个异常是否抛出,但不想处理它, <tt class="xref std std-keyword docutils literal"><span class="pre">raise</span></tt> 语句可以让你很简单的重新抛出该异常:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="ne">NameError</span><span class="p">(</span><span class="s">'HiThere'</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="ne">NameError</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'An exception flew by!'</span>
<span class="gp">... </span> <span class="k">raise</span>
<span class="gp">...</span>
<span class="go">An exception flew by!</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">2</span>, in <span class="n">?</span>
<span class="gr">NameError</span>: <span class="n">HiThere</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-userexceptions">
<span id="id6"></span><h2>8.5. 用户自定义异常<a class="headerlink" href="#tut-userexceptions" title="Permalink to this headline">¶</a></h2>
<p>在程序中可以通过创建新的异常类型来命名自己的异常(Python 类的内容请参见 <a class="reference internal" href="classes.html#tut-classes"><em>类</em></a> )。异常类通常应该直接或间接的从 <tt class="xref py py-exc docutils literal"><span class="pre">Exception</span></tt> 类派生,例如:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="n">MyError</span><span class="p">(</span><span class="mi">2</span><span class="o">*</span><span class="mi">2</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="n">MyError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'My exception occurred, value:'</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">My exception occurred, value: 4</span>
<span class="gp">>>> </span><span class="k">raise</span> <span class="n">MyError</span><span class="p">(</span><span class="s">'oops!'</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">__main__.MyError</span>: <span class="n">'oops!'</span>
</pre></div>
</div>
<p>在这个例子中,<tt class="xref py py-class docutils literal"><span class="pre">Exception</span></tt> 默认的 <tt class="xref py py-meth docutils literal"><span class="pre">__init__()</span></tt> 被覆盖。新的方式简单的创建 <em>value</em> 属性。这就替换了原来创建 <em>args</em> 属性的方式。</p>
<p>异常类中可以定义任何其它类中可以定义的东西,但是通常为了保持简单,只在其中加入几个属性信息,以供异常处理句柄提取。如果一个新创建的模块中需要抛出几种不同的错误时,一个通常的作法是为该模块定义一个异常基类,然后针对不同的错误类型派生出对应的异常子类:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Error</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="sd">"""Base class for exceptions in this module."""</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">InputError</span><span class="p">(</span><span class="n">Error</span><span class="p">):</span>
<span class="sd">"""Exception raised for errors in the input.</span>
<span class="sd"> Attributes:</span>
<span class="sd"> expression -- input expression in which the error occurred</span>
<span class="sd"> message -- explanation of the error</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">expression</span> <span class="o">=</span> <span class="n">expression</span>
<span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span>
<span class="k">class</span> <span class="nc">TransitionError</span><span class="p">(</span><span class="n">Error</span><span class="p">):</span>
<span class="sd">"""Raised when an operation attempts a state transition that's not</span>
<span class="sd"> allowed.</span>
<span class="sd"> Attributes:</span>
<span class="sd"> previous -- state at beginning of transition</span>
<span class="sd"> next -- attempted new state</span>
<span class="sd"> message -- explanation of why the specific transition is not allowed</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">previous</span><span class="p">,</span> <span class="nb">next</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">previous</span> <span class="o">=</span> <span class="n">previous</span>
<span class="bp">self</span><span class="o">.</span><span class="n">next</span> <span class="o">=</span> <span class="nb">next</span>
<span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span>
</pre></div>
</div>
<p>与标准异常相似,大多数异常的命名都以 “Error” 结尾。</p>
<p>很多标准模块中都定义了自己的异常,用以报告在他们所定义的函数中可能发生的错误。关于类的进一步信息请参见 <a class="reference internal" href="classes.html#tut-classes"><em>类</em></a> 一章。</p>
</div>
<div class="section" id="tut-cleanup">
<span id="id7"></span><h2>8.6. 定义清理行为<a class="headerlink" href="#tut-cleanup" title="Permalink to this headline">¶</a></h2>
<p><tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句还有另一个可选的子句,目的在于定义在任何情况下都一定要执行的功能。例如</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">raise</span> <span class="ne">KeyboardInterrupt</span>
<span class="gp">... </span><span class="k">finally</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">'Goodbye, world!'</span>
<span class="gp">...</span>
<span class="go">Goodbye, world!</span>
<span class="nc">KeyboardInterrupt</span>
</pre></div>
</div>
<p>不管有没有发生异常, <em>finally子句</em> 在程序离开 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 后都一定会被执行。当 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句中发生了未被 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 捕获的异常(或者它发生在 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 或 <tt class="xref std std-keyword docutils literal"><span class="pre">else</span></tt> 子句中),在 <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句执行完后它会被重新抛出。 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句经由 <tt class="xref std std-keyword docutils literal"><span class="pre">break</span></tt> ,<tt class="xref std std-keyword docutils literal"><span class="pre">continue</span></tt> 或 <tt class="xref std std-keyword docutils literal"><span class="pre">return</span></tt> 语句退 出也一样会执行 <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句。以下是一个更复杂些的例子(在同 一个 <tt class="xref std std-keyword docutils literal"><span class="pre">try</span></tt> 语句中的 <tt class="xref std std-keyword docutils literal"><span class="pre">except</span></tt> 和 <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句的工作方式与 Python 2.5 一样)</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="k">def</span> <span class="nf">divide</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">result</span> <span class="o">=</span> <span class="n">x</span> <span class="o">/</span> <span class="n">y</span>
<span class="gp">... </span> <span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">"division by zero!"</span>
<span class="gp">... </span> <span class="k">else</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">"result is"</span><span class="p">,</span> <span class="n">result</span>
<span class="gp">... </span> <span class="k">finally</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">print</span> <span class="s">"executing finally clause"</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="n">divide</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="go">result is 2</span>
<span class="go">executing finally clause</span>
<span class="gp">>>> </span><span class="n">divide</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="go">division by zero!</span>
<span class="go">executing finally clause</span>
<span class="gp">>>> </span><span class="n">divide</span><span class="p">(</span><span class="s">"2"</span><span class="p">,</span> <span class="s">"1"</span><span class="p">)</span>
<span class="go">executing finally clause</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">3</span>, in <span class="n">divide</span>
<span class="gr">TypeError</span>: <span class="n">unsupported operand type(s) for /: 'str' and 'str'</span>
</pre></div>
</div>
<p>如你所见, <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句在任何情况下都会执 行。 <tt class="xref py py-exc docutils literal"><span class="pre">TypeError</span></tt> 在两个字符串相除的时候抛出,未被 except 子句捕获,因此在 <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句执行完毕后重新抛出。</p>
<p>在真实场景的应用程序中, <tt class="xref std std-keyword docutils literal"><span class="pre">finally</span></tt> 子句用于释放外部资源(文件 或网络连接之类的),无论它们的使用过程中是否出错。</p>
</div>
<div class="section" id="tut-cleanup-with">
<span id="id8"></span><h2>8.7. 预定义清理行为<a class="headerlink" href="#tut-cleanup-with" title="Permalink to this headline">¶</a></h2>
<p>有些对象定义了标准的清理行为,无论对象操作是否成功,不再需要该对象的时 候就会起作用。以下示例尝试打开文件并把内容打印到屏幕上。:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s">"myfile.txt"</span><span class="p">):</span>
<span class="k">print</span> <span class="n">line</span>
</pre></div>
</div>
<p>这段代码的问题在于在代码执行完后没有立即关闭打开的文件。这在简单的脚本 里没什么,但是大型应用程序就会出问题。 <tt class="xref std std-keyword docutils literal"><span class="pre">with</span></tt> 语句使得文件之类的对象可以 确保总能及时准确地进行清理。:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"myfile.txt"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">:</span>
<span class="k">print</span> <span class="n">line</span>
</pre></div>
</div>
<p>语句执行后,文件 <em>f</em> 总会被关闭,即使是在处理文件中的数据时出错也一样。 其它对象是否提供了预定义的清理行为要查看它们的文档。</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">8. 错误和异常</a><ul>
<li><a class="reference internal" href="#tut-syntaxerrors">8.1. 语法错误</a></li>
<li><a class="reference internal" href="#tut-exceptions">8.2. 异常</a></li>
<li><a class="reference internal" href="#tut-handling">8.3. 异常处理</a></li>
<li><a class="reference internal" href="#tut-raising">8.4. 抛出异常</a></li>
<li><a class="reference internal" href="#tut-userexceptions">8.5. 用户自定义异常</a></li>
<li><a class="reference internal" href="#tut-cleanup">8.6. 定义清理行为</a></li>
<li><a class="reference internal" href="#tut-cleanup-with">8.7. 预定义清理行为</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="inputoutput.html"
title="previous chapter">7. 输入和输出</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="classes.html"
title="next chapter">9. 类</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/errors.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 首页侧边 -->
<ins class="adsbygoogle"
style="display:inline-block;width:200px;height:200px"
data-ad-client="ca-pub-3421553373953599"
data-ad-slot="3551838308"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="classes.html" title="9. 类"
>next</a> |</li>
<li class="right" >
<a href="inputoutput.html" title="7. 输入和输出"
>previous</a> |</li>
<li><a href="index.html">Python tutorial 2.7 documentation</a> »</li>
</ul>
</div>
<div class="footer">
<p>
© Copyright Translate by march.liu, Reorganize by D.D 2013. Created using
<a href="http://sphinx.pocoo.org/">Sphinx</a>
1.2.
</p>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?9adc7a1c86496c8e2bc61c4f8fc92d30";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<p><a href="http://www.miitbeian.gov.cn/">京ICP备14002119号-1</a></p>
<hr/>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- pythondoc 首页下方 -->
<ins class="adsbygoogle"
style="display:inline-block;width:970px;height:90px"
data-ad-client="ca-pub-3421553373953599"
data-ad-slot="6985889234"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</body>
</html>