@@ -70,25 +70,30 @@ exception.
7070
7171```py
7272>> > try :
73- ... print (int (' 123 ' ))
73+ ... print (int (' lol ' ))
7474... except ValueError :
7575... print (" Oops!" )
7676...
77- 123
77+ Oops!
78+ >> >
79+ ```
80+
81+ The except part doesn' t run if the try part succeeds.
82+
83+ ```py
7884>> > try :
79- ... print (int ( ' lol ' ) )
85+ ... print (" Hello World! " )
8086... except ValueError :
81- ... print (" Oops !" )
87+ ... print (" What the heck? Printing failed !" )
8288...
83- Oops !
89+ Hello World !
8490>> >
8591```
8692
8793ValueError is raised when something gets an invalid value, but the
8894value' s type is correct. In this case, `int` can take a string as an
89- argument, but the string needs to contain a number, not `lol` .
90-
91- If the type is wrong, we will get a TypeError instead.
95+ argument, but the string needs to contain a number, not `lol` . If
96+ the type is wrong, we will get a TypeError instead.
9297
9398```py
9499>> > 123 + ' hello'
@@ -98,6 +103,20 @@ TypeError: unsupported operand type(s) for +: 'int' and 'str'
98103>> >
99104```
100105
106+ Catching ValueError doesn' t catch TypeErrors.
107+
108+ ```py
109+ >> > try :
110+ ... 123 + ' hello'
111+ ... except ValueError :
112+ ... print (" wrong value" )
113+ ...
114+ Traceback (most recent call last):
115+ File " <stdin>" , line 2 , in < module>
116+ TypeError : unsupported operand type (s) for + : ' int' and ' str'
117+ >> >
118+ ```
119+
101120Exceptions always interrupt the code even if we catch them. Here the
102121print never runs because it' s after the error but inside the `try`
103122block. Everything after the try block runs normally.
@@ -152,6 +171,24 @@ wrong type
152171
153172Seems to be working.
154173
174+ We can catch multiple exceptions by catching a tuple of exceptions:
175+
176+ ```py
177+ >> > try :
178+ ... 123 + ' hello'
179+ ... except (ValueError , TypeError ):
180+ ... print (' wrong value or type' )
181+ ...
182+ wrong value or type
183+ >> > try :
184+ ... int (' lol' )
185+ ... except (ValueError , TypeError ):
186+ ... print (' wrong value or type' )
187+ ...
188+ wrong value or type
189+ >> >
190+ ```
191+
155192Catching `Exception ` will catch all errors. We' ll learn more about why
156193it does that in a moment.
157194
@@ -203,7 +240,8 @@ There's many things that can go wrong in the `try` block. If something
203240goes wrong all we have is an oops message that doesn't tell us which
204241line caused the problem. This makes fixing problems a lot harder. If we
205242want to catch exceptions we need to be specific about what exactly we
206- want to catch instead of catching everything we can.
243+ want to catch and where instead of catching everything we can in the
244+ whole program.
207245
208246There's nothing wrong with doing things like this:
209247
@@ -218,6 +256,8 @@ except OSError: # we can't read the file but we can work without it
218256Usually catching errors that the user has caused is also a good idea:
219257
220258``` py
259+ import sys
260+
221261text = input (" Enter a number: " )
222262try :
223263 number = int (text)
@@ -229,53 +269,62 @@ print("Your number doubled is %d." % (number * 2))
229269
230270## Raising exceptions
231271
232- Sometimes you may end up doing something like this:
233-
234- ``` py
235- if number < 0 :
236- print (" ERROR: number must be non-negative" )
237- ```
272+ Now we know how to create exceptions and how to handle errors that
273+ Python creates. But we can also create error messages manually. This
274+ is known as ** raising an exception** and ** throwing an exception** .
238275
239- But that's not ideal. If there is an error, the code prints an error
240- message but it still keeps running. People using your code also don't know
241- which line in ** their** code caused the error.
242-
243- Instead you can ** raise an exception** yourself. Sometimes this is also
244- called ** throwing an exception** .
276+ Raising an exception is easy. All we need to do is to type ` raise `
277+ and then an exception we want to raise:
245278
246279``` py
247- if number < 0 :
248- raise ValueError (" number must be non-negative" )
280+ >> > raise ValueError (" lol is not a number" )
281+ Traceback (most recent call last):
282+ File " <stdin>" , line 1 , in < module>
283+ ValueError : lol is not a number
284+ >> >
249285```
250286
251- Let's try that on the interactive prompt, and see what that does .
287+ Of course, we can also raise an exception from a variable .
252288
253289``` py
254- >> > raise ValueError (" number must be non-negative" )
290+ >> > oops = ValueError (" lol is not a number" )
291+ >> > raise oops
255292Traceback (most recent call last):
256293 File " <stdin>" , line 1 , in < module>
257- ValueError : number must be non - negative
294+ ValueError : lol is not a number
258295>> >
259296```
260297
261- Of course, we can also raise an exception from a variable.
298+ If we [ define a function] ( defining-functions.md ) that raises an
299+ exception and call it we'll notice that the error message also
300+ says which functions we ran to get to that error.
262301
263302``` py
264- >> > oops = ValueError (" number must be non-negative" )
265- >> > raise oops
303+ >> > def oops ():
304+ ... raise ValueError (" oh no!" )
305+ ...
306+ >> > def do_the_oops ():
307+ ... oops()
308+ ...
309+ >> > do_the_oops()
266310Traceback (most recent call last):
267311 File " <stdin>" , line 1 , in < module>
268- ValueError : number must be non- negative
312+ File " <stdin>" , line 2 , in do_the_oops
313+ File " <stdin>" , line 2 , in oops
314+ ValueError : oh no!
269315>> >
270316```
271317
318+ If our code was in a file we would also see the line of code
319+ that raised the error.
320+
272321## When should we raise exceptions?
273322
274323Back in [ the module chapter] ( modules.md ) we learned to display error
275324messages by printing to ` sys.stderr ` and then calling ` sys.exit(1) ` , so
276325when should we use that and when should we raise an exception?
277326
278- Exceptions are meant for ** programmers** , so if we're writing a module
327+ Exceptions are meant for ** programmers** , so if we are writing a module
279328that other people will import we should probably use exceptions. For
280329other errors (for example, if the ** user** of the program has done
281330something wrong) it's usually better to use ` sys.stderr ` and ` sys.exit ` .
@@ -348,7 +397,7 @@ older than mine, but they should be mostly similar.
348397Catching an exception also catches everything that's under it in this
349398tree. For example, catching ` OSError ` catches errors that we typically
350399get when [ processing files] ( files.md ) , and catching Exception catches
351- all errors. You don't need to remember this tree, running
400+ all of these errors. You don't need to remember this tree, running
352401` help('builtins') ` should display a larger tree that this is a part of.
353402
354403## Summary
@@ -362,3 +411,64 @@ all errors. You don't need to remember this tree, running
362411 is also known as throwing exceptions.
363412- Raise exceptions if they are meant to be displayed for programmers and
364413 use ` sys.stderr ` and ` sys.exit ` otherwise.
414+
415+ ## Examples
416+
417+ Keep asking a number from the user until it's entered correctly.
418+
419+ ``` py
420+ while True :
421+ try :
422+ number = int (input (" Enter a number: " ))
423+ break
424+ except ValueError :
425+ print (" That's not a valid number! Try again." )
426+
427+ print (" Your number doubled is:" , number * 2 )
428+ ```
429+
430+ This program allows the user to customize the message it prints by
431+ modifying a file the greeting is stored in, and it can create the
432+ file for the user if it doesn't exist already. This example also uses
433+ things from [ the file chapter] ( files.md ) , [ the function defining
434+ chapter] ( defining-functions.md ) and [ the module chapter] ( modules.md ) .
435+
436+ ``` py
437+ # These are here so you can change them to customize the program
438+ # easily.
439+ default_greeting = " Hello World!"
440+ filename = " greeting.txt"
441+
442+
443+ import sys
444+
445+ def askyesno (question ):
446+ while True :
447+ answer = input (question + ' (y or n) ' )
448+ if answer == ' Y' or answer == ' y' :
449+ return True
450+ if answer == ' N' or answer == ' n' :
451+ return False
452+
453+ def greet ():
454+ with open (filename, ' r' ) as f:
455+ for line in f:
456+ print (line.rstrip(' \n ' ))
457+
458+ try :
459+ greet()
460+ except OSError :
461+ print (" Cannot read '%s '!" % filename, file = sys.stderr)
462+ if askyesno(" Would you like to create a default greeting file?" ):
463+ try :
464+ with open (filename, ' w' ) as f:
465+ print (default_greeting, file = f)
466+ except OSError :
467+ print (" Cannot create '%s ' :(" % filename, file = sys.stderr)
468+ sys.exit(1 ) # time to give up
469+ greet()
470+ ```
471+
472+ ***
473+
474+ You may use this tutorial at your own risk. See [ LICENSE] ( LICENSE ) .
0 commit comments