try and except
try and except are the statements that catch an error while a program runs, so it can deal with the problem and carry on.
Last updated: 30 Sep, 2026 · Python 3.14
One bad answer stopped the loop in Stand-in model. Catching the error lets the program move on to the next ticket.
Syntax:
try:
... # code that may fail
except SomeError:
... # runs only if SomeError was raisedCatching a JSON error
import json
def ask_model(ticket_text):
text = ticket_text.lower()
if "charged" in text or "refund" in text:
return '{"category": "billing", "priority": 4}'
if "parcel" in text or "arrived" in text:
return '{"category": "shipping", "priority": 3}'
return "I am not sure how to sort this one."
with open("tickets.json") as f:
tickets = json.load(f)answer = ask_model("How do I change my password?")
try:
data = json.loads(answer)
except json.JSONDecodeError:
data = {"category": "other", "priority": 1}
print(data){'category': 'other', 'priority': 1}json.JSONDecodeError is the error the traceback in Stand-in model called json.decoder.JSONDecodeError: the same error, with a shorter name. Python runs the try block. If json.loads raises a JSONDecodeError, it jumps to the except block instead of stopping, and the program continues after it.
Name the error you expect. except json.JSONDecodeError handles only unreadable JSON. A typo in a variable name inside the try still stops the program, which is what you want, because a typo is a bug to fix rather than an answer to work around.
View the code here
[
{
"id": 1,
"customer": "Asha",
"text": "I was charged twice for one order"
},
{
"id": 2,
"customer": "Ben",
"text": "My parcel has not arrived"
},
{
"id": 3,
"customer": "Chen",
"text": "Can I get a refund for the blue mug?"
},
{
"id": 4,
"customer": "Dara",
"text": "How do I change my password?"
},
{
"id": 5,
"customer": "Eli",
"text": "The parcel arrived but the box was crushed"
}
]
Keeping the loop going
unsorted = []
for ticket in tickets:
try:
data = json.loads(ask_model(ticket["text"]))
except json.JSONDecodeError:
unsorted.append(ticket["id"])
continue
print(ticket["id"], data["category"])
print("Needs a person:", unsorted)1 billing 2 shipping 3 billing 5 shipping Needs a person: [4]
continue skips the rest of this pass through the loop and moves to the next ticket. All five are handled, and the one the model could not sort is kept for a person instead of being lost.
Raising your own error
Sometimes the value parses but is still wrong. raise stops with an error you choose, and a message saying why.
def check_priority(priority):
if priority < 1 or priority > 5:
raise ValueError(f"priority must be 1 to 5, got {priority}")
return priority
print(check_priority(4))
print(check_priority(9))4
Traceback (most recent call last):
File "main.py", line 7, in <module>
print(check_priority(9))
File "main.py", line 3, in check_priority
raise ValueError(f"priority must be 1 to 5, got {priority}")
ValueError: priority must be 1 to 5, got 9try:
check_priority(9)
except ValueError as error:
print("rejected:", error)rejected: priority must be 1 to 5, got 9
If you are building one file, delete the print(check_priority(9)) line first: the error above stops the file there. as error gives the caught error a name, and printing it shows its message. Checking every field by hand like this gets long; Pydantic models hands the job to Pydantic.
except SomeError vs a bare except
except json.JSONDecodeError: | except: | |
|---|---|---|
| Catches | Only unreadable JSON | Every error, typos included |
| A bug in your code | Still stops the program | Is hidden |
| Use it | Almost always | Almost never |
Where try and except show up in AI code
- Reading a model's answer that may not be the JSON you asked for.
- Network calls that can fail, retried in Timeouts and retries.
- Checking values and raising a clear error when they are out of range.
except: catches everything, including your own typos, so a broken program looks like it works. Name the error you expect.Related
- Previous: Stand-in model
- Next: Classes
- Reference: Errors and Exceptions in the Python tutorial
- Remove
continue. There is no error, but ticket 4 now printsbilling. Why? (datastill holds ticket 3's answer.) - Put
data = json.loads(answr), with the typo, inside the firsttry. Does theexceptcatch it? - Call
check_priority(0)inside thetry.
This is what real progress feels like.