11# Exceptions
22
3- So far we have made programs that ask the user to enter a string.
3+ So far we have made programs that ask the user to enter a string, and
4+ we also know how to convert that to an integer.
45
56``` py
67text = input (" Enter something: " )
7- print (" Your text twice:" , text* 2 )
8- ```
9-
10- That works.
11-
12- ```
13- Enter something: hello
14- Your text twice: hellohello
15- ```
16-
17- But if the user enters a number, it's not going to be multiplied by two.
18-
19- ```
20- Enter something: 3
21- Your text twice: 33
22- ```
23-
24- Let's use ` int ` to convert that to an integer:
25-
26- ``` py
27- text = input (" Enter a number: " )
288number = int (text)
29- print (" Your number twice :" , number* 2 )
9+ print (" Your number doubled :" , number* 2 )
3010```
3111
32- That works...
12+ That works.
3313
3414```
3515Enter a number: 3
3616Your number twice: 6
3717```
3818
39- ...unless the user does not enter a number.
19+ But that doesn't work if the user does not enter a number.
4020
4121``` py
4222Enter a number: lol
@@ -53,7 +33,8 @@ So how can we fix that?
5333In the previous example we got a ValueError . ValueError is an
5434** exception** . In other words, ValueError is an error that can occur
5535in our program. If an exception occurs, the program will stop and we
56- get an error message.
36+ get an error message. The interactive prompt will display an error
37+ message and keep going.
5738
5839```py
5940>> > int (' lol' )
@@ -63,28 +44,21 @@ ValueError: invalid literal for int() with base 10: 'lol'
6344>> >
6445```
6546
66- Exceptions are classes, just like int and str . We' ll talk more about
67- classes later in this tutorial.
47+ Exceptions are [classes](classes.md).
6848
6949```py
70- >> > str
71- < class ' str' >
72- >> > int
73- < class ' int' >
7450>> > ValueError
7551< class ' ValueError' >
7652>> >
7753```
7854
79- You can also create an exception. You won't get an error message by doing
55+ We can also create exceptions. We won' t get an error message by doing
8056that, but we' ll use this for displaying our own error messages later.
8157
8258```py
8359>> > the_problem = ValueError (' oh no' )
8460>> > the_problem
8561ValueError (' oh no' ,)
86- >> > type (the_problem)
87- < class ' ValueError' >
8862>> >
8963```
9064
@@ -124,6 +98,21 @@ TypeError: unsupported operand type(s) for +: 'int' and 'str'
12498>> >
12599```
126100
101+ Exceptions always interrupt the code even if we catch them. Here the
102+ print never runs because it' s after the error but inside the `try`
103+ block. Everything after the try block runs normally.
104+
105+ ```py
106+ >> > try :
107+ ... 123 + ' hello'
108+ ... print (" This doesn't get printed." )
109+ ... except TypeError :
110+ ... print (" Oops!" )
111+ ...
112+ Oops!
113+ >> >
114+ ```
115+
127116Does an `except ValueError ` also catch TypeErrors?
128117
129118```py
@@ -163,7 +152,28 @@ wrong type
163152
164153Seems to be working.
165154
166- It' s also possible to catch an exception, and store it in a variable:
155+ Catching `Exception ` will catch all errors. We' ll learn more about why
156+ it does that in a moment.
157+
158+ ```py
159+ >> > try :
160+ ... 123 + ' hello'
161+ ... except Exception :
162+ ... print (" Oops!" )
163+ ...
164+ Oops!
165+ >> > try :
166+ ... int (' lol' )
167+ ... except Exception :
168+ ... print (" Oops!" )
169+ ...
170+ Oops!
171+ >> >
172+ ```
173+
174+ It's also possible to catch an exception and store it in a variable.
175+ Here we are catching an exception that Python created and storing it in
176+ ` our_error ` .
167177
168178``` py
169179>> > try :
@@ -178,10 +188,48 @@ TypeError("unsupported operand type(s) for +: 'int' and 'str'",)
178188>> >
179189```
180190
191+ ## When should we catch exceptions?
192+
193+ Never do things like this:
194+
195+ ``` py
196+ try :
197+ # many lines of code
198+ except Exception :
199+ print (" Oops! Something went wrong." )
200+ ```
201+
202+ There's many things that can go wrong in the ` try ` block. If something
203+ goes wrong all we have is an oops message that doesn't tell us which
204+ line caused the problem. This makes fixing problems a lot harder. If we
205+ want to catch exceptions we need to be specific about what exactly we
206+ want to catch instead of catching everything we can.
207+
208+ There's nothing wrong with doing things like this:
209+
210+ ``` py
211+ try :
212+ with open (' some file' , ' r' ) as f:
213+ content = f.read()
214+ except OSError : # we can't read the file but we can work without it
215+ content = some_default_content
216+ ```
217+
218+ Usually catching errors that the user has caused is also a good idea:
219+
220+ ``` py
221+ text = input (" Enter a number: " )
222+ try :
223+ number = int (text)
224+ except ValueError :
225+ print (" '%s ' is not a number." % text, file = sys.stderr)
226+ sys.exit(1 )
227+ print (" Your number doubled is %d ." % (number * 2 ))
228+ ```
229+
181230## Raising exceptions
182231
183- When working on something that other programmers are going to use,
184- you may end up doing something like this:
232+ Sometimes you may end up doing something like this:
185233
186234``` py
187235if number < 0 :
@@ -190,10 +238,10 @@ if number < 0:
190238
191239But that's not ideal. If there is an error, the code prints an error
192240message but it still keeps running. People using your code also don't know
193- which line in their code caused the error.
241+ which line in ** their** code caused the error.
194242
195- Instead you can ** raise ** an exception yourself. Sometimes this is also
196- called ** throwing** an exception.
243+ Instead you can ** raise an exception** yourself. Sometimes this is also
244+ called ** throwing an exception** .
197245
198246``` py
199247if number < 0 :
@@ -210,19 +258,107 @@ ValueError: number must be non-negative
210258>> >
211259```
212260
213- It's working .
261+ Of course, we can also raise an exception from a variable .
214262
215- ** TODO:** except Exception
263+ ``` py
264+ >> > oops = ValueError (" number must be non-negative" )
265+ >> > raise oops
266+ Traceback (most recent call last):
267+ File " <stdin>" , line 1 , in < module>
268+ ValueError : number must be non- negative
269+ >> >
270+ ```
216271
217- ** TODO:** introduce assert here?
272+ ## When should we raise exceptions?
273+
274+ Back in [ the module chapter] ( modules.md ) we learned to display error
275+ messages by printing to ` sys.stderr ` and then calling ` sys.exit(1) ` , so
276+ when should we use that and when should we raise an exception?
277+
278+ Exceptions are meant for ** programmers** , so if we're writing a module
279+ that other people will import we should probably use exceptions. For
280+ other errors (for example, if the ** user** of the program has done
281+ something wrong) it's usually better to use ` sys.stderr ` and ` sys.exit ` .
282+
283+ ## Exception hierarchy
284+
285+ Exceptions are organized like this. I made this tree diagram with
286+ [ this program] ( https://github.com/Akuli/classtree/ ) on Python 3.4. You
287+ may have more or less exceptions than I have if your Python is newer or
288+ older than mine, but they should be mostly similar.
289+
290+ Exception
291+ ├── ArithmeticError
292+ │ ├── FloatingPointError
293+ │ ├── OverflowError
294+ │ └── ZeroDivisionError
295+ ├── AssertionError
296+ ├── AttributeError
297+ ├── BufferError
298+ ├── EOFError
299+ ├── ImportError
300+ ├── LookupError
301+ │ ├── IndexError
302+ │ └── KeyError
303+ ├── MemoryError
304+ ├── NameError
305+ │ └── UnboundLocalError
306+ ├── OSError
307+ │ ├── BlockingIOError
308+ │ ├── ChildProcessError
309+ │ ├── ConnectionError
310+ │ │ ├── BrokenPipeError
311+ │ │ ├── ConnectionAbortedError
312+ │ │ ├── ConnectionRefusedError
313+ │ │ └── ConnectionResetError
314+ │ ├── FileExistsError
315+ │ ├── FileNotFoundError
316+ │ ├── InterruptedError
317+ │ ├── IsADirectoryError
318+ │ ├── NotADirectoryError
319+ │ ├── PermissionError
320+ │ ├── ProcessLookupError
321+ │ └── TimeoutError
322+ ├── ReferenceError
323+ ├── RuntimeError
324+ │ └── NotImplementedError
325+ ├── StopIteration
326+ ├── SyntaxError
327+ │ └── IndentationError
328+ │ └── TabError
329+ ├── SystemError
330+ ├── TypeError
331+ ├── ValueError
332+ │ └── UnicodeError
333+ │ ├── UnicodeDecodeError
334+ │ ├── UnicodeEncodeError
335+ │ └── UnicodeTranslateError
336+ └── Warning
337+ ├── BytesWarning
338+ ├── DeprecationWarning
339+ ├── FutureWarning
340+ ├── ImportWarning
341+ ├── PendingDeprecationWarning
342+ ├── ResourceWarning
343+ ├── RuntimeWarning
344+ ├── SyntaxWarning
345+ ├── UnicodeWarning
346+ └── UserWarning
347+
348+ Catching an exception also catches everything that's under it in this
349+ tree. For example, catching ` OSError ` catches errors that we typically
350+ get when [ processing files] ( files.md ) , and catching Exception catches
351+ all errors. You don't need to remember this tree, running
352+ ` help('builtins') ` should display a larger tree that this is a part of.
218353
219354## Summary
220355
221- - Exceptions can be used just like any other variables .
356+ - Exceptions are classes and they can be used just like all other classes .
222357- ValueError and TypeError are some of the most commonly used exceptions.
223358- The ` try ` and ` except ` keywords can be used for attempting to do
224- something and then doing something else if it causes an error. This
225- is known as catching exceptions. You can use one ` try ` statement with
226- multiple ` except ` statements.
227- - It's also possible to raise exceptions with the ` raise ` keyword. This
359+ something and then doing something else if we get an error. This is
360+ known as catching exceptions.
361+ - It's possible to raise exceptions with the ` raise ` keyword. This
228362 is also known as throwing exceptions.
363+ - Raise exceptions if they are meant to be displayed for programmers and
364+ use ` sys.stderr ` and ` sys.exit ` otherwise.
0 commit comments