16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.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
16.3.14. Assignments
# %% About
# - Name: Exception Catch One
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try returning `value` converted to `float`
# 3. If `ValueError` occurs, print 'Invalid value'
# 4. Run doctests - all must succeed
# %% Polish
# 1. Zmodyfikuj funkcję `convert`
# 2. Spróbuj zwrócić przekonwertowane `value` do `float`
# 3. Jeżeli wystąpi `ValueError`, wypisz 'Invalid value'
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `try`
# - `except`
# - `print()`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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'
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
convert: Callable[[Any], float|None]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Many
# - Difficulty: easy
# - Lines: 6
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try returning `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. Spróbuj zwrócić 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()`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
convert: Callable[[Any], float|None]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Many
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try returning `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. Spróbuj zwrócić 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()`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
result: Callable[[Any], float|None]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Exception
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try returning `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. Spróbuj zwrócić 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`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable
convert: Callable[[object], float|None]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Message
# - Difficulty: easy
# - Lines: 4
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try returning `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. Spróbuj zwrócić 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`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
convert: Callable[[Any], float|None]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Else
# - Difficulty: easy
# - Lines: 6
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try converting argument `value` to `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`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
convert: Callable[[Any], bool]
# %% Data
# %% Result
def convert(value):
return float(value)
# %% About
# - Name: Exception Catch Finally
# - Difficulty: easy
# - Lines: 2
# - Minutes: 3
# %% 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
# %% English
# 1. Modify function `convert`
# 2. Try converting argument `value` to `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`
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 10), \
'Python 3.10+ 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
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
from typing import Callable, Any
convert: Callable[[Any], bool]
# %% Data
# %% Result
def convert(value):
try:
float(value)
except Exception:
return False
else:
return True