-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlesson_10
More file actions
355 lines (266 loc) Β· 9.64 KB
/
lesson_10
File metadata and controls
355 lines (266 loc) Β· 9.64 KB
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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# π― Lesson 10: Exception Handling
Welcome to one of the most practical lessons in your Python journey! Exception handling is how we write **robust, professional code** that doesn't crash when something goes wrong.
---
## π₯ Why This Matters in Healthcare
Imagine your narcotic inventory system in production:
- A user enters "five" instead of 5 for quantity
- The JSON file gets corrupted mid-write
- Someone tries to withdraw 50ml of Fentanyl when only 10ml exists
- A new drug entry is missing the required schedule field
**Without exception handling:** Your program crashes, loses data, and creates chaos in the OR.
**With exception handling:** Your program catches the error, logs it, shows a helpful message, and continues safely.
This is the difference between **student code** and **production code**.
---
## π§ The Core Concept
Think of exceptions like **adverse events in anesthesia**:
1. **Monitor for problems** (`try`) - You're watching vitals
2. **Respond to specific issues** (`except`) - Hypotension? Give vasopressor. Hypoxia? Check ventilator.
3. **Always do this regardless** (`finally`) - Document everything, even if the case went perfectly
4. **Success path** (`else`) - Patient stable? Continue with the plan.
---
## π The Syntax
```python
try:
# Code that might cause an error
risky_operation()
except SpecificError:
# Handle that specific problem
handle_it()
except AnotherError as e:
# Handle a different problem, access error details with 'e'
print(f"Problem: {e}")
else:
# Only runs if NO exceptions occurred
print("Everything went smoothly!")
finally:
# ALWAYS runs, even if there was an error
cleanup()
```
---
## π Common Built-in Exceptions
| Exception | When It Happens | Healthcare Example |
|-----------|-----------------|-------------------|
| `ValueError` | Wrong type of value | User enters "ten" instead of 10 |
| `KeyError` | Dictionary key doesn't exist | Looking for drug "Fentany1" (typo) |
| `FileNotFoundError` | File doesn't exist | `inventory.json` was deleted |
| `IndexError` | List index out of range | Accessing `drugs[100]` when list has 10 items |
| `ZeroDivisionError` | Dividing by zero | Calculating per-case usage when cases = 0 |
| `TypeError` | Wrong data type | Adding string + int |
| `AttributeError` | Object has no attribute | Calling `drug.price` when Drug has no price attribute |
---
## ποΈ Example: Safe User Input
**Before (crashes on bad input):**
```python
quantity = int(input("Enter quantity: ")) # User types "five" β CRASH!
```
**After (handles bad input gracefully):**
```python
try:
quantity = int(input("Enter quantity: "))
except ValueError:
print("β Please enter a number, not text!")
quantity = 0 # Safe default
```
---
## π₯ Example: Safe File Operations
```python
def load_inventory():
try:
with open("inventory.json", "r") as f:
return json.load(f)
except FileNotFoundError:
print("β οΈ No inventory file found. Creating new inventory...")
return [] # Start fresh
except json.JSONDecodeError:
print("β Inventory file is corrupted!")
# Maybe load backup, or start fresh
return []
```
---
## π― Multiple Exceptions
You can catch different errors and respond differently:
```python
def withdraw_drug(drug_name, amount):
try:
drug = inventory[drug_name] # Might raise KeyError
new_balance = drug['balance'] - amount
if new_balance < 0:
raise ValueError("Insufficient stock!") # We create this error!
drug['balance'] = new_balance
except KeyError:
print(f"β Drug '{drug_name}' not found in inventory")
except ValueError as e:
print(f"β Withdrawal failed: {e}")
else:
print(f"β
Withdrew {amount}ml of {drug_name}")
finally:
save_inventory() # ALWAYS save, even if withdrawal failed
```
---
## π Creating Custom Exceptions
For healthcare-specific errors:
```python
class InsufficientStockError(Exception):
"""Raised when trying to withdraw more than available"""
pass
class InvalidScheduleError(Exception):
"""Raised when drug schedule is not I, II, III, IV, or V"""
pass
class ExpiredDrugError(Exception):
"""Raised when trying to use an expired medication"""
pass
# Usage:
def validate_schedule(schedule):
valid_schedules = ["I", "II", "III", "IV", "V"]
if schedule not in valid_schedules:
raise InvalidScheduleError(f"Schedule must be one of {valid_schedules}")
```
---
## π Best Practices
1. **Be Specific** - Catch specific exceptions, not generic `except:` (too broad)
2. **Fail Gracefully** - Don't hide errors silently; inform the user
3. **Log Critical Errors** - In production, you need audit trails
4. **Don't Overuse** - Not every line needs try/except; use where failures are likely
5. **Clean Up Resources** - Use `finally` for closing files, saving data, etc.
---
## β What NOT to Do
```python
# DON'T: Catch everything and ignore it
try:
# Some code
pass
except:
pass # Silent failure = debugging nightmare!
# DON'T: Catch too broadly
try:
result = complex_calculation()
except Exception:
print("Something went wrong!") # What went wrong? Where? Why?
```
---
## π§ͺ Your Mission: Make Your Inventory System Bulletproof
### **Core Task: Add Exception Handling Throughout**
I want you to go through your **entire narcotic inventory system** and add proper exception handling. Here's where:
#### **1. User Input Validation**
- When asking for quantities (must be positive integers)
- When asking for drug names
- When asking for HSA-ID
- When selecting menu options
#### **2. File Operations**
- Loading `inventory.json`
- Saving `inventory.json`
- Loading `transactions.json`
#### **3. Drug Operations**
- Withdrawing drugs (insufficient stock)
- Adding drugs (validating schedule, name, balance)
- Finding drugs by name
#### **4. Create Custom Exceptions**
Create at least these three:
```python
class InsufficientStockError(Exception):
pass
class InvalidScheduleError(Exception):
pass
class InvalidHSAIDError(Exception):
pass
```
---
### **Success Criteria**
Your program should:
- β
**Never crash** - handle all reasonable bad inputs gracefully
- β
Show **helpful error messages** - not just "error occurred"
- β
**Always save data** - use `finally` blocks for critical operations
- β
Use **custom exceptions** - for healthcare-specific validation
- β
**Log errors** - print what went wrong so you can debug
---
### **Example Scenarios to Handle**
Test your system with these:
1. **User enters text when asked for number**
```
Enter quantity to withdraw: five
β Invalid input. Please enter a number.
```
2. **User tries to withdraw more than available**
```
Enter amount: 50
β Insufficient stock! Only 10.0ml available.
```
3. **User enters invalid drug name**
```
Enter drug name: Fentanylll
β Drug 'Fentanylll' not found in inventory.
```
4. **Corrupted inventory.json**
```
β οΈ Inventory file corrupted. Starting fresh inventory.
```
5. **User enters invalid menu choice**
```
Enter choice: 99
β Invalid choice. Please enter 1-5.
```
---
### π **Bonus Challenges** (Optional)
1. **Retry Logic**: If user enters bad input, give them 3 chances before returning to menu
2. **Backup System**: Before saving, create `inventory_backup.json` in case save fails
3. **Error Logging**: Write errors to `error_log.txt` with timestamps
4. **Validation Function**: Create a `validate_positive_number()` function you can reuse everywhere
---
## π Think About
Before you start coding:
1. **Where in your current code could things go wrong?**
- User input?
- File operations?
- Math operations (division by zero)?
- Dictionary lookups?
2. **What should happen when each error occurs?**
- Show message and retry?
- Show message and return to menu?
- Log it and continue?
- Create backup and try again?
3. **Which operations must ALWAYS complete?**
- Saving data?
- Logging transactions?
- Closing files?
---
## π¦ Getting Started
Here's a skeleton to get you thinking (don't just copy this - adapt it to your code):
```python
def withdraw_drug():
"""Handle drug withdrawal with full error handling"""
try:
# Get drug name (what could go wrong here?)
drug_name = input("Enter drug name: ").strip()
# Find drug in inventory (what could go wrong here?)
# ...
# Get withdrawal amount (what could go wrong here?)
# ...
# Check sufficient stock (what could go wrong here?)
# ...
# Update balance
# ...
except ValueError as e:
# Handle value errors
print(f"β Invalid input: {e}")
except KeyError:
# Handle missing drug
print(f"β Drug '{drug_name}' not found")
except InsufficientStockError as e:
# Handle insufficient stock
print(f"β {e}")
else:
# Only if everything succeeded
print("β
Withdrawal successful!")
finally:
# ALWAYS do this
save_inventory()
```
---
## π Submission
When you're done:
1. Show me your exception handling approach for **one function** (pick your favorite)
2. Tell me: **What was the hardest error to handle? Why?**
3. Test your system with bad inputs - **what breaks it now?** (There's always something!)
---
**Remember:** The goal isn't to make code that *never* has errors. The goal is to make code that **handles errors gracefully** and keeps your OR running safely.
Good luck! πͺ Start with the user input validation - that's where most errors happen!