Skip to content

Commit 5924cbf

Browse files
committed
add issue#29
1 parent e9ad4ab commit 5924cbf

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

issues/29.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# pycobytes[29] := Expect the Exception
2+
<!-- #SQUARK live!
3+
| dest = issues/(issue)/29
4+
| title = Expect the Exception
5+
| head = Expect the Exception
6+
| index = 29
7+
| tags =
8+
| date = 2025 May 16
9+
-->
10+
11+
> *A good programmer designs a ship that can't sink, then designs the lifeboats for when it does.*
12+
13+
Hey pops!
14+
15+
Ahh! A syntax error! Nooo!
16+
17+
What’s a `SyntaxError` anyway?
18+
19+
An **error**, technically speaking, refers to anything that’s wrong in your program – unintended behaviour, unsuitable data, inaccurate logic, etc. Some – but not all – errors can interrupt the flow of the program, which you usually see as a crash.
20+
21+
```bash
22+
C:Users/Rick > python main.py
23+
Hello world!
24+
SyntaxError: unmatched ')'
25+
```
26+
27+
When this happens, it means an **Exception** has been raised. If unhandled, these terminate the program and output that lovely error message.
28+
29+
```py
30+
Traceback (most recent call last):
31+
File "C:/Users/Rick/demo.py", line 39, in <module>
32+
handler.handle()
33+
File "C:/Users/Rick/demo.py", line 31, in handle
34+
respond(*args, **kwargs)
35+
TypeError: handler.<locals>.handle.<locals>.respond() missing 1 required positional arguments: 'status'
36+
```
37+
38+
We call this output a **stack trace**, since it shows all the layers that led to the exception being raised. This is a brilliant tool for debugging, and it’s why other people online will ask for your entire error output (rather than just the single line with the message) when helping you debug.
39+
40+
```py
41+
# what does this mean??
42+
SyntaxError: EOL while scanning string literal
43+
```
44+
45+
You’ve likely encountered plenty of exceptions in your time programming – `IndexError`, `TypeError`, `ValueError`.
46+
47+
It’s inevitable for errors to arise in a program, and this certainty only increases with complexity. Often we overlook error handling when we start out programming, but gracefully and *properly* handling errors is critical in production software.
48+
49+
We can ‘catch’ and respond to errors using **try-except**:
50+
51+
```py
52+
try:
53+
do_something()
54+
except:
55+
panic()
56+
```
57+
58+
If an exception is raised while running the code inside `try:`, then that code will terminate, but it won’t terminate the entire program. Instead, the code inside `except:` is ran. Here’s where we can put our error handling.
59+
60+
```py
61+
>>> try:
62+
l = [0, 1, 2, 3, 4]
63+
print(l[5])
64+
l.append(5) # never happens since previous line raises exception
65+
print("this never runs")
66+
67+
except:
68+
print("l was not long enough, L")
69+
70+
l was not long enough, L
71+
```
72+
73+
We can selectively respond to specific exception types by naming them:
74+
75+
```py
76+
>>> try:
77+
n = int(input("What would you like to divide by? ))
78+
print(1 / n)
79+
80+
except TypeError:
81+
print("Just enter a number, mate")
82+
83+
except ZeroDivisonError:
84+
print("You can’t divide by 0, muppet")
85+
86+
What would you like to divide by? 0
87+
You can’t divide by 0, muppet
88+
```
89+
90+
And Python makes it easy for you to respond to multiple exceptions with the same block – just provide a `tuple` of those you want to catch:
91+
92+
```py
93+
try:
94+
do_it()
95+
except (TypeError, ValueError):
96+
failed_to_do_it()
97+
except IndexError:
98+
database_empty()
99+
```
100+
101+
Remember the for-else loop? We have the same pattern here – an `else:` block under the try-except runs if *no* exception is raised. In other words, the code ran successfully:
102+
103+
```py
104+
>>> try:
105+
print(0 ** 0)
106+
except:
107+
print("okk Python did not like that")
108+
else:
109+
print("guess we’re good to go then")
110+
111+
guess we’re good to go then
112+
```
113+
114+
This is different to just putting the code after the try-except, because remember that
115+
116+
```py
117+
try:
118+
print(0 / 0)
119+
except:
120+
print("error")
121+
else:
122+
print("no error")
123+
124+
print("but this always runs, regardless of error or no error")
125+
```
126+
127+
Even though the exception is thrown, the program as a whole doesn’t stop, because we’ve now got the `except` block absorbing the exception.
128+
129+
We can throw exceptions manually using the `raise` keyword:
130+
131+
```py
132+
try:
133+
raise TypeError
134+
except:
135+
print("huh wonder how that happened")
136+
```
137+
138+
Usually this is followed by the `Exception` class (or object) you want to raise, but you can also use it blank:
139+
140+
```py
141+
try:
142+
if database.empty:
143+
raise
144+
except:
145+
print("oh")
146+
```
147+
148+
You’d never actually write the following in production code (I hope), but you might have it as an intermediate during debugging:
149+
150+
```py
151+
try:
152+
will_go_wrong()
153+
except:
154+
raise
155+
```
156+
157+
This of course does nothing since it just re-raises the error. But you might, say, comment out your usual error handling code and replace it with a `raise` if you wanted the program to crash and output the stack trace.
158+
159+
```py
160+
try:
161+
work()
162+
except:
163+
# if game.state == "idle":
164+
# game.nonblock_debug()
165+
# else:
166+
# game.exit_on_error()
167+
raise
168+
```
169+
170+
And finally, if you need to use the exception you encounter as an object, assign to a variable with `as`:
171+
172+
```py
173+
try:
174+
except IndexError as e:
175+
print("error encountered")
176+
print(e) # outputs error trace
177+
raise e # forwards exception
178+
```
179+
180+
These are the basics for expecting and capturing exceptions. How you handle them, of course, is a totally different story. (Pro tip: just printing the exception and ignoring it is NOT the solution.)
181+
182+
In future, we’ll look at how you can define your own exceptions, and use them for sophisticated state and control flow management!
183+
184+
185+
<br>
186+
187+
188+
---
189+
190+
<div align="center">
191+
192+
[![The Codeless Code, Case 87](../assets/issues/29-codeless.png)](http://thecodelesscode.com/case/87)
193+
194+
[*The Codeless Code*, Case 87](http://thecodelesscode.com/case/87)
195+
196+
</div>
197+

0 commit comments

Comments
 (0)