forked from swcarpentry/python-novice-inflammation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
07-errors.html
314 lines (302 loc) · 24.2 KB
/
07-errors.html
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<title>Software Carpentry: Programming with Python</title>
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap-theme.css" />
<link rel="stylesheet" type="text/css" href="css/swc.css" />
<link rel="alternate" type="application/rss+xml" title="Software Carpentry Blog" href="http://software-carpentry.org/feed.xml"/>
<meta charset="UTF-8" />
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body class="lesson">
<div class="container card">
<div class="banner">
<a href="http://software-carpentry.org" title="Software Carpentry">
<img alt="Software Carpentry banner" src="img/software-carpentry-banner.png" />
</a>
</div>
<article>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<a href="index.html"><h1 class="title">Programming with Python</h1></a>
<h2 class="subtitle">Errors and Exceptions</h2>
<section class="objectives panel panel-warning">
<div class="panel-heading">
<h2 id="learning-objectives"><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2>
</div>
<div class="panel-body">
<ul>
<li>To be able to read a traceback, and determine the following relevant pieces of information:
<ul>
<li>The file, function, and line number on which the error occurred</li>
<li>The type of the error</li>
<li>The error message</li>
</ul></li>
<li>To be able to describe the types of situations in which the following errors occur:
<ul>
<li><code>SyntaxError</code> and <code>IndentationError</code></li>
<li><code>NameError</code></li>
<li><code>IndexError</code></li>
<li><code>FileNotFoundError</code></li>
</ul></li>
</ul>
</div>
</section>
<p>Every programmer encounters errors, both those who are just beginning, and those who have been programming for years. Encountering errors and exceptions can be very frustrating at times, and can make coding feel like a hopeless endeavour. However, understanding what the different types of errors are and when you are likely to encounter them can help a lot. Once you know <em>why</em> you get certain types of errors, they become much easier to fix.</p>
<p>Errors in Python have a very specific form, called a <a href="reference.html#traceback">traceback</a>. Let’s examine one:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="im">import</span> errors_01
errors_01.favorite_ice_cream()</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-1-9d0462a5b07c> in <module>()
1 import errors_01
----> 2 errors_01.favorite_ice_cream()
/Users/jhamrick/project/swc/novice/python/errors_01.pyc in favorite_ice_cream()
5 "strawberry"
6 ]
----> 7 print(ice_creams[3])
IndexError: list index out of range</code></pre>
<p>This particular traceback has two levels. You can determine the number of levels by looking for the number of arrows on the left hand side. In this case:</p>
<ol style="list-style-type: decimal">
<li><p>The first shows code from the cell above, with an arrow pointing to Line 2 (which is <code>favorite_ice_cream()</code>).</p></li>
<li><p>The second shows some code in another function (<code>favorite_ice_cream</code>, located in the file <code>errors_01.py</code>), with an arrow pointing to Line 7 (which is <code>print(ice_creams[3])</code>).</p></li>
</ol>
<p>The last level is the actual place where the error occurred. The other level(s) show what function the program executed to get to the next level down. So, in this case, the program first performed a <a href="reference.html#function-call">function call</a> to the function <code>favorite_ice_cream</code>. Inside this function, the program encountered an error on Line 7, when it tried to run the code <code>print(ice_creams[3])</code>.</p>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h2 id="long-tracebacks"><span class="glyphicon glyphicon-pushpin"></span>Long Tracebacks</h2>
</div>
<div class="panel-body">
<p>Sometimes, you might see a traceback that is very long – sometimes they might even be 20 levels deep! This can make it seem like something horrible happened, but really it just means that your program called many functions before it ran into the error. Most of the time, you can just pay attention to the bottom-most level, which is the actual place where the error occurred.</p>
</div>
</aside>
<p>So what error did the program actually encounter? In the last line of the traceback, Python helpfully tells us the category or type of error (in this case, it is an <code>IndexError</code>) and a more detailed error message (in this case, it says “list index out of range”).</p>
<p>If you encounter an error and don’t know what it means, it is still important to read the traceback closely. That way, if you fix the error, but encounter a new one, you can tell that the error changed. Additionally, sometimes just knowing <em>where</em> the error occurred is enough to fix it, even if you don’t entirely understand the message.</p>
<p>If you do encounter an error you don’t recognize, try looking at the <a href="http://docs.python.org/3/library/exceptions.html">official documentation on errors</a>. However, note that you may not always be able to find the error there, as it is possible to create custom errors. In that case, hopefully the custom error message is informative enough to help you figure out what went wrong.</p>
<h2 id="syntax-errors">Syntax Errors</h2>
<p>When you forget a colon at the end of a line, accidentally add one space too many when indenting under an <code>if</code> statement, or forget a parenthesis, you will encounter a <a href="reference.html#syntax-error">syntax error</a>. This means that Python couldn’t figure out how to read your program. This is similar to forgetting punctuation in English:</p>
<blockquote>
<p>this text is difficult to read there is no punctuation there is also no capitalization why is this hard because you have to figure out where each sentence ends you also have to figure out where each sentence begins to some extent it might be ambiguous if there should be a sentence break or not</p>
</blockquote>
<p>People can typically figure out what is meant by text with no punctuation, but people are much smarter than computers. If Python doesn’t know how to read the program, it will just give up and inform you with an error. For example:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> some_function()
msg <span class="op">=</span> <span class="st">"hello, world!"</span>
<span class="bu">print</span>(msg)
<span class="cf">return</span> msg</code></pre></div>
<pre class="error"><code> File "<ipython-input-3-6bb841ea1423>", line 1
def some_function()
^
SyntaxError: invalid syntax</code></pre>
<p>Here, Python tells us that there is a <code>SyntaxError</code> on line 1, and even puts a little arrow in the place where there is an issue. In this case the problem is that the function definition is missing a colon at the end.</p>
<p>Actually, the function above has <em>two</em> issues with syntax. If we fix the problem with the colon, we see that there is <em>also</em> an <code>IndentationError</code>, which means that the lines in the function definition do not all have the same indentation:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> some_function():
msg <span class="op">=</span> <span class="st">"hello, world!"</span>
<span class="bu">print</span>(msg)
<span class="cf">return</span> msg</code></pre></div>
<pre class="error"><code> File "<ipython-input-4-ae290e7659cb>", line 4
return msg
^
IndentationError: unexpected indent</code></pre>
<p>Both <code>SyntaxError</code> and <code>IndentationError</code> indicate a problem with the syntax of your program, but an <code>IndentationError</code> is more specific: it <em>always</em> means that there is a problem with how your code is indented.</p>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h2 id="tabs-and-spaces"><span class="glyphicon glyphicon-pushpin"></span>Tabs and Spaces</h2>
</div>
<div class="panel-body">
<p>A quick note on indentation errors: they can sometimes be insidious, especially if you are mixing spaces and tabs. Because they are both <a href="reference.html#whitespace">whitespace</a>, it is difficult to visually tell the difference. The IPython notebook actually gives us a bit of a hint, but not all Python editors will do that. In the following example, the first two lines are using a tab for indentation, while the third line uses four spaces:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> some_function():
msg <span class="op">=</span> <span class="st">"hello, world!"</span>
<span class="bu">print</span>(msg)
<span class="cf">return</span> msg</code></pre></div>
<pre class="error"><code> File "<ipython-input-5-653b36fbcd41>", line 4
return msg
^
IndentationError: unindent does not match any outer indentation level</code></pre>
<p>By default, one tab is equivalent to eight spaces, so the only way to mix tabs and spaces is to make it look like this. In general, is is better to just never use tabs and always use spaces, because it can make things very confusing.</p>
</div>
</aside>
<h2 id="variable-name-errors">Variable Name Errors</h2>
<p>Another very common type of error is called a <code>NameError</code>, and occurs when you try to use a variable that does not exist. For example:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="bu">print</span>(a)</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-7-9d7b17ad5387> in <module>()
----> 1 print(a)
NameError: name 'a' is not defined</code></pre>
<p>Variable name errors come with some of the most informative error messages, which are usually of the form “name ‘the_variable_name’ is not defined”.</p>
<p>Why does this error message occur? That’s harder question to answer, because it depends on what your code is supposed to do. However, there are a few very common reasons why you might have an undefined variable. The first is that you meant to use a <a href="reference.html#string">string</a>, but forgot to put quotes around it:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="bu">print</span>(hello)</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-8-9553ee03b645> in <module>()
----> 1 print(hello)
NameError: name 'hello' is not defined</code></pre>
<p>The second is that you just forgot to create the variable before using it. In the following example, <code>count</code> should have been defined (e.g., with <code>count = 0</code>) before the for loop:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="cf">for</span> number <span class="op">in</span> <span class="bu">range</span>(<span class="dv">10</span>):
count <span class="op">=</span> count <span class="op">+</span> number
<span class="bu">print</span>(<span class="st">"The count is: "</span> <span class="op">+</span> <span class="bu">str</span>(count))</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-9-dd6a12d7ca5c> in <module>()
1 for number in range(10):
----> 2 count = count + number
3 print("The count is: " + str(count))
NameError: name 'count' is not defined</code></pre>
<p>Finally, the third possibility is that you made a typo when you were writing your code. Let’s say we fixed the error above by adding the line <code>Count = 0</code> before the for loop. Frustratingly, this actually does not fix the error. Remember that variables are <a href="reference.html#case-sensitive">case-sensitive</a>, so the variable <code>count</code> is different from <code>Count</code>. We still get the same error, because we still have not defined <code>count</code>:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">Count <span class="op">=</span> <span class="dv">0</span>
<span class="cf">for</span> number <span class="op">in</span> <span class="bu">range</span>(<span class="dv">10</span>):
count <span class="op">=</span> count <span class="op">+</span> number
<span class="bu">print</span>(<span class="st">"The count is: "</span> <span class="op">+</span> <span class="bu">str</span>(count))</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-10-d77d40059aea> in <module>()
1 Count = 0
2 for number in range(10):
----> 3 count = count + number
4 print("The count is: " + str(count))
NameError: name 'count' is not defined</code></pre>
<h2 id="item-errors">Item Errors</h2>
<p>Next up are errors having to do with containers (like lists and dictionaries) and the items within them. If you try to access an item in a list or a dictionary that does not exist, then you will get an error. This makes sense: if you asked someone what day they would like to get coffee, and they answered “caturday”, you might be a bit annoyed. Python gets similarly annoyed if you try to ask it for an item that doesn’t exist:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">letters <span class="op">=</span> [<span class="st">'a'</span>, <span class="st">'b'</span>, <span class="st">'c'</span>]
<span class="bu">print</span>(<span class="st">"Letter #1 is "</span> <span class="op">+</span> letters[<span class="dv">0</span>])
<span class="bu">print</span>(<span class="st">"Letter #2 is "</span> <span class="op">+</span> letters[<span class="dv">1</span>])
<span class="bu">print</span>(<span class="st">"Letter #3 is "</span> <span class="op">+</span> letters[<span class="dv">2</span>])
<span class="bu">print</span>(<span class="st">"Letter #4 is "</span> <span class="op">+</span> letters[<span class="dv">3</span>])</code></pre></div>
<pre class="output"><code>Letter #1 is a
Letter #2 is b
Letter #3 is c</code></pre>
<pre class="error"><code>---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-11-d817f55b7d6c> in <module>()
3 print("Letter #2 is " + letters[1])
4 print("Letter #3 is " + letters[2])
----> 5 print("Letter #4 is " + letters[3])
IndexError: list index out of range</code></pre>
<p>Here, Python is telling us that there is an <code>IndexError</code> in our code, meaning we tried to access a list index that did not exist.</p>
<h2 id="file-errors">File Errors</h2>
<p>The last type of error we’ll cover today are those associated with reading and writing files: <code>FileNotFoundError</code>. If you try to read a file that does not exist, you will receive a <code>FileNotFoundError</code> telling you so.</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">file_handle <span class="op">=</span> <span class="bu">open</span>(<span class="st">'myfile.txt'</span>, <span class="st">'r'</span>)</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
<ipython-input-14-f6e1ac4aee96> in <module>()
----> 1 file_handle = open('myfile.txt', 'r')
FileNotFoundError: [Errno 2] No such file or directory: 'myfile.txt'</code></pre>
<p>One reason for receiving this error is that you specified an incorrect path to the file. For example, if I am currently in a folder called <code>myproject</code>, and I have a file in <code>myproject/writing/myfile.txt</code>, but I try to just open <code>myfile.txt</code>, this will fail. The correct path would be <code>writing/myfile.txt</code>. It is also possible (like with <code>NameError</code>) that you just made a typo.</p>
<p>A related issue can occur if you use the “read” flag instead of the “write” flag. Python will not give you an error if you try to open a file for writing when the file does not exist. However, if you meant to open a file for reading, but accidentally opened it for writing, and then try to read from it, you will get an <code>UnsupportedOperation</code> error telling you that the file was not opened for reading:</p>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">file_handle <span class="op">=</span> <span class="bu">open</span>(<span class="st">'myfile.txt'</span>, <span class="st">'w'</span>)
file_handle.read()</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-15-b846479bc61f> in <module>()
1 file_handle = open('myfile.txt', 'w')
----> 2 file_handle.read()
UnsupportedOperation: not readable</code></pre>
<p>These are the most common errors with files, though many others exist. If you get an error that you’ve never seen before, searching the Internet for that error type often reveals common reasons why you might get that error.</p>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h2 id="reading-error-messages"><span class="glyphicon glyphicon-pencil"></span>Reading Error Messages</h2>
</div>
<div class="panel-body">
<p>Read the traceback below, and identify the following pieces of information about it:</p>
<ol style="list-style-type: decimal">
<li>How many levels does the traceback have?</li>
<li>What is the file name where the error occurred?</li>
<li>What is the function name where the error occurred?</li>
<li>On which line number in this function did the error occurr?</li>
<li>What is the type of error?</li>
<li>What is the error message?</li>
</ol>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="im">import</span> errors_02
errors_02.print_friday_message()</code></pre></div>
<pre class="error"><code>---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-2-e4c4cbafeeb5> in <module>()
1 import errors_02
----> 2 errors_02.print_friday_message()
/Users/jhamrick/project/swc/novice/python/errors_02.py in print_friday_message()
13
14 def print_friday_message():
---> 15 print_message("Friday")
/Users/jhamrick/project/swc/novice/python/errors_02.py in print_message(day)
9 "sunday": "Aw, the weekend is almost over."
10 }
---> 11 print(messages[day])
12
13
KeyError: 'Friday'</code></pre>
</div>
</section>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h2 id="identifying-syntax-errors"><span class="glyphicon glyphicon-pencil"></span>Identifying Syntax Errors</h2>
</div>
<div class="panel-body">
<ol style="list-style-type: decimal">
<li>Read the code below, and (without running it) try to identify what the errors are.</li>
<li>Run the code, and read the error message. Is it a <code>SyntaxError</code> or an <code>IndentationError</code>?</li>
<li>Fix the error.</li>
<li>Repeat steps 2 and 3, until you have fixed all the errors.</li>
</ol>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="kw">def</span> another_function
<span class="bu">print</span>(<span class="st">"Syntax errors are annoying."</span>)
<span class="bu">print</span>(<span class="st">"But at least python tells us about them!"</span>)
<span class="bu">print</span>(<span class="st">"So they are usually not too hard to fix."</span>)</code></pre></div>
</div>
</section>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h2 id="identifying-variable-name-errors"><span class="glyphicon glyphicon-pencil"></span>Identifying Variable Name Errors</h2>
</div>
<div class="panel-body">
<ol style="list-style-type: decimal">
<li>Read the code below, and (without running it) try to identify what the errors are.</li>
<li>Run the code, and read the error message. What type of <code>NameError</code> do you think this is? In other words, is it a string with no quotes, a misspelled variable, or a variable that should have been defined but was not?</li>
<li>Fix the error.</li>
<li>Repeat steps 2 and 3, until you have fixed all the errors.</li>
</ol>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python"><span class="cf">for</span> number <span class="op">in</span> <span class="bu">range</span>(<span class="dv">10</span>):
<span class="co"># use a if the number is a multiple of 3, otherwise use b</span>
<span class="cf">if</span> (Number <span class="op">%</span> <span class="dv">3</span>) <span class="op">==</span> <span class="dv">0</span>:
message <span class="op">=</span> message <span class="op">+</span> a
<span class="cf">else</span>:
message <span class="op">=</span> message <span class="op">+</span> <span class="st">"b"</span>
<span class="bu">print</span>(message)</code></pre></div>
</div>
</section>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h2 id="identifying-item-errors"><span class="glyphicon glyphicon-pencil"></span>Identifying Item Errors</h2>
</div>
<div class="panel-body">
<ol style="list-style-type: decimal">
<li>Read the code below, and (without running it) try to identify what the errors are.</li>
<li>Run the code, and read the error message. What type of error is it?</li>
<li>Fix the error.</li>
</ol>
<div class="sourceCode"><pre class="sourceCode python"><code class="sourceCode python">seasons <span class="op">=</span> [<span class="st">'Spring'</span>, <span class="st">'Summer'</span>, <span class="st">'Fall'</span>, <span class="st">'Winter'</span>]
<span class="bu">print</span>(<span class="st">'My favorite season is '</span>, seasons[<span class="dv">4</span>])</code></pre></div>
</div>
</section>
</div>
</div>
</article>
<div class="footer">
<a class="label swc-blue-bg" href="http://software-carpentry.org">Software Carpentry</a>
<a class="label swc-blue-bg" href="https://github.com/swcarpentry/python-novice-inflammation">Source</a>
<a class="label swc-blue-bg" href="mailto:[email protected]">Contact</a>
<a class="label swc-blue-bg" href="LICENSE.html">License</a>
</div>
</div>
<!-- Javascript placed at the end of the document so the pages load faster -->
<script src="http://software-carpentry.org/v5/js/jquery-1.9.1.min.js"></script>
<script src="css/bootstrap/bootstrap-js/bootstrap.js"></script>
</body>
</html>