try, except, else and finallyDEBUG:my_code:Debug level print for local logger working
Create two loggers lazy and eager and make lazy print only critical messages, and eager print all messages.
DEBUG level for more infoTraceback (most recent call last):
File "/private/tmp/call.py", line 7, in <module>
caller()
File "/private/tmp/call.py", line 2, in caller
div_by_zero()
File "/private/tmp/call.py", line 5, in div_by_zero
1 / 0
~~^~~
ZeroDivisionError: division by zero
Traceback (most recent call last):
File "/private/tmp/call.py", line 7, in <module>
caller()
File "/private/tmp/call.py", line 2, in caller
div_by_zero()
File "/private/tmp/call.py", line 5, in div_by_zero
1 / 0
~~^~~
ZeroDivisionError: division by zero
Start from the bottom
File "/private/tmp/call.py", line 5, in div_by_zero
1 / 0
~~^~~
ZeroDivisionError: division by zero
This is what tripped the code in the end. If this is deep in some library, work your way down from the top to see where in your code you went into the libraries (usually the mistake is on you and not on the library).
In a Python interpreter, try to trigger different exceptions:
1 / 0int("one")"hello"[42]{"a": 1}["b"]open("does_not_exist.txt")Read each traceback. What is the exception type? What does the message tell you?
try to run code that might fail.except to handle errors gracefully.import logging
logging.basicConfig(level=logging.INFO)
try:
s = input("Enter a number to be squared: ")
num = float(s)
except ValueError:
logging.error("can't convert %s to a number!", s)
else:
logging.info(f"You entered: {num}, the square is {num**2}")
finally:
logging.info("I'll call it a day now.")finallyInstead of try/finally for resource cleanup, prefer with:
The with statement guarantees cleanup — even if an exception occurs.
Write a function safe_divide(a, b) that:
a / bZeroDivisionError and prints a message instead of crashingTypeError (e.g. safe_divide("x", 2)) and prints a different messageint value to the caller, scripts rely on this0 = success, non-zero = failure1sys.exit() (see python docs)sys.exit() at the top level (__main__) — functions should raise, not exitOften, you can use a built-in exception for your scenario.
| Exception | When to use |
|---|---|
ValueError |
Right type, wrong value (e.g. int("abc")) |
TypeError |
Wrong type entirely (e.g. len(42)) |
KeyError |
Dictionary key not found |
FileNotFoundError |
File or directory does not exist |
RuntimeError |
Something went wrong at runtime, no better fit |
NotImplementedError |
Method exists but is not implemented yet |
Keeps the origin clear.
…
The error message
Traceback (most recent call last):
File "<python-input-0>", line 3, in div_one
num = float(val)
ValueError: could not convert string to float: 'one'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<python-input-0>", line 11, in <module>
print (div_one("one"))
~~~~~~~^^^^^^^
File "<python-input-0>", line 5, in div_one
raise ValueError(
...<2 lines>...
) from ve
ValueError: div_one will divide 1 by its argument. We need something convertible to float as argument.
Use logger.exception() inside an except block to log the message and the full traceback:
ERROR:root:Failed to convert input to int
Traceback (most recent call last):
File "<python-input-0>", line 4, in <module>
int("not a number")
~~~^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'not a number'
This bridges logging and error handling — record the problem and its context.
Write a function behave that will raise a BehaviorException, when called with "exceptional" as argument.
Write another function, that calls behave and catches this behavior. Make it log exceptional behavior.
try/exceptNobody reads logs if things don’t crash.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
FunkyError: Funky!
warningsThe warnings module sits between logging and exceptions: