Skip to content

Commit f6777d6

Browse files
committed
new file: exceptions.md
1 parent b7935d0 commit f6777d6

1 file changed

Lines changed: 228 additions & 0 deletions

File tree

exceptions.md

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# Exceptions
2+
3+
So far we have made programs that ask the user to enter a string.
4+
5+
```py
6+
text = 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: ")
28+
number = int(text)
29+
print("Your number twice:", number*2)
30+
```
31+
32+
That works...
33+
34+
```
35+
Enter a number: 3
36+
Your number twice: 6
37+
```
38+
39+
...unless the user does not enter a number.
40+
41+
```py
42+
Enter a number: lol
43+
Traceback (most recent call last):
44+
File "/some/place/file.py", line 2, in <module>
45+
number = int(text)
46+
ValueError: invalid literal for int() with base 10: 'lol'
47+
```
48+
49+
So how can we fix that?
50+
51+
## What are exceptions?
52+
53+
In the previous example we got a ValueError. ValueError is an
54+
**exception**. In other words, ValueError is an error that can occur
55+
in our program. If an exception occurs, the program will stop and we
56+
get an error message.
57+
58+
```py
59+
>>> int('lol')
60+
Traceback (most recent call last):
61+
File "<stdin>", line 1, in <module>
62+
ValueError: invalid literal for int() with base 10: 'lol'
63+
>>>
64+
```
65+
66+
Exceptions are classes, just like int and str. We'll talk more about
67+
classes later in this tutorial.
68+
69+
```py
70+
>>> str
71+
<class 'str'>
72+
>>> int
73+
<class 'int'>
74+
>>> ValueError
75+
<class 'ValueError'>
76+
>>>
77+
```
78+
79+
You can also create an exception. You won't get an error message by doing
80+
that, but we'll use this for displaying our own error messages later.
81+
82+
```py
83+
>>> the_problem = ValueError('oh no')
84+
>>> the_problem
85+
ValueError('oh no',)
86+
>>> type(the_problem)
87+
<class 'ValueError'>
88+
>>>
89+
```
90+
91+
## Catching exceptions
92+
93+
If we need to try to do something and see if we get an exception, we
94+
can use `try` and `except`. This is also known as **catching** the
95+
exception.
96+
97+
```py
98+
>>> try:
99+
... print(int('123'))
100+
... except ValueError:
101+
... print("Oops!")
102+
...
103+
123
104+
>>> try:
105+
... print(int('lol'))
106+
... except ValueError:
107+
... print("Oops!")
108+
...
109+
Oops!
110+
>>>
111+
```
112+
113+
ValueError is raised when something gets an invalid value, but the
114+
value's type is correct. In this case, `int` can take a string as an
115+
argument, but the string needs to contain a number, not `lol`.
116+
117+
If the type is wrong, we will get a TypeError instead.
118+
119+
```py
120+
>>> 123 + 'hello'
121+
Traceback (most recent call last):
122+
File "<stdin>", line 1, in <module>
123+
TypeError: unsupported operand type(s) for +: 'int' and 'str'
124+
>>>
125+
```
126+
127+
Does an `except ValueError` also catch TypeErrors?
128+
129+
```py
130+
>>> try:
131+
... print(123 + 'hello')
132+
... except ValueError:
133+
... print("Oops!")
134+
...
135+
Traceback (most recent call last):
136+
File "<stdin>", line 2, in <module>
137+
TypeError: unsupported operand type(s) for +: 'int' and 'str'
138+
>>>
139+
```
140+
141+
No, it doesn't. But maybe we could except for both ValueError and
142+
TypeError?
143+
144+
```py
145+
>>> try:
146+
... int('lol')
147+
... except ValueError:
148+
... print('wrong value')
149+
... except TypeError:
150+
... print('wrong type')
151+
...
152+
wrong value
153+
>>> try:
154+
... 123 + 'hello'
155+
... except ValueError:
156+
... print('wrong value')
157+
... except TypeError:
158+
... print('wrong type')
159+
...
160+
wrong type
161+
>>>
162+
```
163+
164+
Seems to be working.
165+
166+
It's also possible to catch an exception, and store it in a variable:
167+
168+
```py
169+
>>> try:
170+
... 123 + 'hello'
171+
... except TypeError as e:
172+
... our_error = e
173+
...
174+
>>> our_error
175+
TypeError("unsupported operand type(s) for +: 'int' and 'str'",)
176+
>>> type(our_error)
177+
<class 'TypeError'>
178+
>>>
179+
```
180+
181+
## Raising exceptions
182+
183+
When working on something that other programmers are going to use,
184+
you may end up doing something like this:
185+
186+
```py
187+
if number < 0:
188+
print("ERROR: number must be non-negative")
189+
```
190+
191+
But that's not ideal. If there is an error, the code prints an error
192+
message but it still keeps running. People using your code also don't know
193+
which line in their code caused the error.
194+
195+
Instead you can **raise** an exception yourself. Sometimes this is also
196+
called **throwing** an exception.
197+
198+
```py
199+
if number < 0:
200+
raise ValueError("number must be non-negative")
201+
```
202+
203+
Let's try that on the interactive prompt, and see what that does.
204+
205+
```py
206+
>>> raise ValueError("number must be non-negative")
207+
Traceback (most recent call last):
208+
File "<stdin>", line 1, in <module>
209+
ValueError: number must be non-negative
210+
>>>
211+
```
212+
213+
It's working.
214+
215+
**TODO:** except Exception
216+
217+
**TODO:** introduce assert here?
218+
219+
## Summary
220+
221+
- Exceptions can be used just like any other variables.
222+
- ValueError and TypeError are some of the most commonly used exceptions.
223+
- 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
228+
is also known as throwing exceptions.

0 commit comments

Comments
 (0)