15.3. Exception Catching
try
- block of code that may raise exceptionexcept
- block of code that handles exceptionelse
- block of code that is executed when no exception occurredfinally
- block of code that is executed always (even if there was exception)try
is required and then one of the others blocks
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Permission error')
... except (ConnectionRefusedError, ConnectionAbortedError) as err:
... print(f'Connection error: {err}')
... else:
... print('Login successful')
... finally:
... print('Disconnect')
...
Permission error
Disconnect
15.3.1. Problem
If Python encounter an exception, the whole program crashes
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> login('mwatney', 'Ares3')
Traceback (most recent call last):
PermissionError: Access denied
15.3.2. Solution
Avoid using
except Exception
Always use specific exception like
ValueError
,TypeError
, etc.
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except Exception:
... print('Caught an exception')
...
Caught an exception
15.3.3. Catch Specific Exception
Catch single exception
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Login error')
...
Login error
15.3.4. Catch Exception with Message
Catch single exception
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError as err:
... print(f'Login error: {err}')
...
Login error: Access denied
15.3.5. Catch Different Exceptions
Catch exceptions with different handling
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Login error')
... except ValueError:
... print('Invalid password and/or username')
...
Login error
15.3.6. Catch Multiple Exception
Catch exceptions with the same handling
You can also capture the exception message with
(..., ...) as err
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Permission error')
... except (ConnectionRefusedError, ConnectionAbortedError) as err:
... print(f'Connection error: {err}')
...
Permission error
15.3.7. Else
else
is executed when no exception occurred
>>> def login(username, password):
... pass
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Permission error')
... else:
... print('Login successful')
...
Login successful
15.3.8. Finally
finally
is executed always (even if there was exception)
finally
is executed always (even if there was exception).
Typically it is used to close file, connection or transaction to database:
>>> def login(username, password):
... raise PermissionError('Cannot login')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Permission error')
... finally:
... print('Disconnect')
...
Permission error
Disconnect
15.3.9. Pokemon Exception Handling
"Gotta catch 'em all"
Ctrl-C
raisesKeyboardInterrupt
Operating system shutdown raises
SystemExit
Except without specific exception (this could be a SyntaxError
if future versions of Python):
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>> try:
... login('mwatney', 'Ares3')
... except:
... print('Caught')
...
Caught
This is better, but still to broad:
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>> try:
... login('mwatney', 'Ares3')
... except Exception:
... print('Caught')
...
Caught
Propert way to handle this situation is to catch specific exceptions:
>>> def login(username, password):
... raise PermissionError('Access denied')
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Caught')
...
Caught
15.3.10. Recap
try
- block of code that may raise exceptionexcept
- block of code that handles exceptionelse
- block of code that is executed when no exception occurredfinally
- block of code that is executed always (even if there was exception)try
is required and then one of the others blocks
>>> def login(username, password):
... raise PermissionError('Cannot login')
>>>
>>>
>>> try:
... login('mwatney', 'Ares3')
... except PermissionError:
... print('Permission error')
... except (ConnectionRefusedError, ConnectionAbortedError) as err:
... print(f'Connection error: {err}')
... else:
... print('Login successful')
... finally:
... print('Disconnect')
...
Permission error
Disconnect
15.3.11. Use Case - 1
>>> def database_connect():
... print('Connecting...')
>>>
>>>
>>> try:
... db = database_connect()
... except ConnectionError:
... print('Sorry, no internet connection')
... except PermissionError:
... print('Sorry, permission denied')
... except Exception:
... print('Sorry, unknown error')
... else:
... print('Connection established')
... print('Executing query...')
... finally:
... print('Disconnect from database')
...
Connecting...
Connection established
Executing query...
Disconnect from database
15.3.12. Use Case - 2
>>> try:
... with open('/tmp/myfile.txt') as file:
... print(file.read())
... except FileNotFoundError:
... print('File does not exist')
... except PermissionError:
... print('Permission denied')
...
File does not exist
15.3.13. Use Case - 3
One cannot simply kill program with Ctrl-C
:
>>>
... while True:
... try:
... number = float(input('Type number: '))
... except:
... continue
One can kill program with Ctrl-C
:
>>>
... while True:
... try:
... number = float(input('Type number: '))
... except Exception:
... continue
Proper way to handle this situation:
>>>
... while True:
... try:
... number = float(input('Type number: '))
... except ValueError:
... continue
15.3.14. Assignments
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch One
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Return `value` converted to `float`
# 3. If `ValueError` occurs, print 'Invalid value'
# 4. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Zwróć przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi `ValueError`, wypisz 'Invalid value'
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `print()`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> convert(1)
1.0
>>> convert(1.0)
1.0
>>> convert(1,0)
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> convert('1')
1.0
>>> convert('1.0')
1.0
>>> convert('1,0')
Invalid value
>>> convert((1.0))
1.0
>>> convert((1.0))
1.0
>>> convert((1,0))
Traceback (most recent call last):
TypeError: float() argument must be a string or a real number, not 'tuple'
>>> convert([1])
Traceback (most recent call last):
TypeError: float() argument must be a string or a real number, not 'list'
>>> convert([1.0])
Traceback (most recent call last):
TypeError: float() argument must be a string or a real number, not 'list'
>>> convert([1,0])
Traceback (most recent call last):
TypeError: float() argument must be a string or a real number, not 'list'
"""
# Modify function `convert`
# Return `value` converted to `float`
# If `ValueError` occurs, print 'Invalid value'
# type: Callable[[Any], float|None]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Many
# - Difficulty: easy
# - Lines: 6
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Return `value` converted to `float`
# 3. If `ValueError` occurs, print 'Invalid value'
# 4. If `TypeError` occurs, print 'Invalid type'
# 5. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Zwróć przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi `ValueError`, wypisz 'Invalid value'
# 4. Jeżeli wystąpi `TypeError`, wypisz 'Invalid type'
# 5. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `print()`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> convert(1)
1.0
>>> convert(1.0)
1.0
>>> convert(1,0)
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> convert('1')
1.0
>>> convert('1.0')
1.0
>>> convert('1,0')
Invalid value
>>> convert((1.0))
1.0
>>> convert((1.0))
1.0
>>> convert((1,0))
Invalid type
>>> convert([1])
Invalid type
>>> convert([1.0])
Invalid type
>>> convert([1,0])
Invalid type
"""
# Modify function `convert`
# Return `value` converted to `float`
# If `ValueError` occurs, print 'Invalid value'
# If `TypeError` occurs, print 'Invalid type'
# type: Callable[[Any], float|None]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Many
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Return `value` converted to `float`
# 3. If `ValueError or `TypeError` occurs, print 'Invalid argument'
# 4. Use only one `except`
# 4. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Zwróć przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi `ValueError` lub `TypeError`, wypisz 'Invalid argument'
# 4. Użyj tylko jednego `except`
# 5. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `print()`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> convert(1)
1.0
>>> convert(1.0)
1.0
>>> convert(1,0)
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> convert('1')
1.0
>>> convert('1.0')
1.0
>>> convert('1,0')
Invalid argument
>>> convert((1.0))
1.0
>>> convert((1.0))
1.0
>>> convert((1,0))
Invalid argument
>>> convert([1])
Invalid argument
>>> convert([1.0])
Invalid argument
>>> convert([1,0])
Invalid argument
"""
# Modify function `convert`
# Return `value` converted to `float`
# If `ValueError` or `TypeError` occurs, print 'Invalid argument'
# Use only one `except`
# type: Callable[[Any], float|None]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Exception
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Return `value` converted to `float`
# 3. If any exception occurs, then return `None`
# 4. Do not leave empty `except`
# 5. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Zwróć przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi jakikolwiek wyjątek, to zwróć `None`
# 4. Nie pozostawiaj pustego `except`
# 5. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> print(convert(1))
1.0
>>> print(convert(1.0))
1.0
>>> print(convert(1,0))
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> print(convert('1'))
1.0
>>> print(convert('1.0'))
1.0
>>> print(convert('1,0'))
None
>>> print(convert((1.0)))
1.0
>>> print(convert((1.0)))
1.0
>>> print(convert((1,0)))
None
>>> print(convert([1]))
None
>>> print(convert([1.0]))
None
>>> print(convert([1,0]))
None
"""
# Modify function `convert`
# Return `value` converted to `float`
# If any exception occurs, then return `None`
# Do not leave empty `except`
# type: Callable[[Any], float|None]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Message
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Return `value` converted to `float`
# 3. If any exception occurs, then print error original message and return `None`
# 4. Do not leave empty `except`
# 5. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Zwróć przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi jakikolwiek wyjątek, to wypisz oryginalny komunikat i zwróć `None`
# 4. Nie pozostawiaj pustego `except`
# 5. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> print(convert(1))
1.0
>>> print(convert(1.0))
1.0
>>> print(convert(1,0))
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> print(convert('1'))
1.0
>>> print(convert('1.0'))
1.0
>>> print(convert('1,0'))
could not convert string to float: '1,0'
None
>>> print(convert((1.0)))
1.0
>>> print(convert((1.0)))
1.0
>>> print(convert((1,0)))
float() argument must be a string or a real number, not 'tuple'
None
>>> print(convert([1]))
float() argument must be a string or a real number, not 'list'
None
>>> print(convert([1.0]))
float() argument must be a string or a real number, not 'list'
None
>>> print(convert([1,0]))
float() argument must be a string or a real number, not 'list'
None
"""
# Modify function `convert`
# Return `value` converted to `float`
# If any exception occurs, then print error original message and return `None`
# Do not leave empty `except`
# type: Callable[[Any], float|None]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Else
# - Difficulty: easy
# - Lines: 6
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Try converting argument `value` do `float`
# 3. If any exception occurs, then return `False`
# 4. If no exception occurs, then return `True`
# 5. Use `try`, `except`, `else`
# 6. Do not leave empty `except`
# 7. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Spróbuj przekonwertować argument `value` do `float`
# 3. Jeżeli wystąpi jakikolwiek wyjątek, to zwróć `False`
# 4. Jeżeli nie wystąpi żaden wyjątek, to zwróć `True`
# 5. Użyj `try`, `except`, `else`
# 6. Nie pozostawiaj pustego `except`
# 7. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `else`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> convert(1)
True
>>> convert(1.0)
True
>>> convert(1,0)
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> convert('1')
True
>>> convert('1.0')
True
>>> convert('1,0')
False
>>> convert((1.0))
True
>>> convert((1.0))
True
>>> convert((1,0))
False
>>> convert([1])
False
>>> convert([1.0])
False
>>> convert([1,0])
False
"""
# Modify function `convert`
# Try converting argument `value` as a `float`
# If any exception occurs, then return `False`
# If no exception occurs, then return `True`
# Use `try`, `except`, `else`
# Do not leave empty `except`
# type: Callable[[Any], bool]
def convert(value):
return float(value)
# FIXME: Python 3.9 has different exception message then newer versions
# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% About
# - Name: Exception Catch Finally
# - Difficulty: easy
# - Lines: 2
# - Minutes: 3
# %% English
# 1. Modify function `convert`
# 2. Try converting argument `value` do `float`
# 3. If any exception occurs, then return `False`
# 4. If no exception occurs, then return `True`
# 5. After all (doesn't matter if exception occurred or not), print 'done'
# 6. Use `try`, `except`, `else`, `finally`
# 7. Do not leave empty `except`
# 8. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Spróbuj przekonwertować argument `value` do `float`
# 3. Jeżeli wystąpi jakikolwiek wyjątek, to zwróć `False`
# 4. Jeżeli nie wystąpi żaden wyjątek, to zwróć `True`
# 5. Po wszystkim (niezależnie czy wystąpił wyjątek czy nie), wypisz 'done'
# 6. Użyj `try`, `except`, `else`, `finally`
# 7. Nie pozostawiaj pustego `except`
# 8. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `else`
# - `finally`
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> result = open(__file__).read()
>>> assert 'except'+':' not in result, \
'Do not leave empty except'
>>> convert(1)
done
True
>>> convert(1.0)
done
True
>>> convert(1,0)
Traceback (most recent call last):
TypeError: convert() takes 1 positional argument but 2 were given
>>> convert('1')
done
True
>>> convert('1.0')
done
True
>>> convert('1,0')
done
False
>>> convert((1.0))
done
True
>>> convert((1.0))
done
True
>>> convert((1,0))
done
False
>>> convert([1])
done
False
>>> convert([1.0])
done
False
>>> convert([1,0])
done
False
"""
# Modify function `convert`
# Try converting argument `value` do `float`
# If any exception occurs, then return `False`
# If no exception occurs, then return `True`
# After all (doesn't matter if exception occurred or not), print 'done'
# Use `try`, `except`, `else`, `finally`
# Do not leave empty `except`
# type: Callable[[Any], bool]
def convert(value):
try:
float(value)
except Exception:
return False
else:
return True