2.1. Syntax Exceptions — Python
2.1.1. Custom Exceptions
Class which inherits from
ExceptionExceptions should have
Errorat the end of their names
>>> class MyError(Exception): ... pass
Raise without a message:
>>> raise MyError Traceback (most recent call last): MyError
Raise with a message:
>>> class MyError(Exception): ... pass >>> >>> >>> raise MyError('More verbose description') Traceback (most recent call last): MyError: More verbose description
Catch:
>>> class MyError(Exception): ... pass >>> >>> def run(): ... raise MyError('We have a problem') >>> >>> >>> try: ... run() ... except MyError as err: ... print(f'Exception happened: {err}') Exception happened: We have a problem
2.1.2. Embed Exception
Exception can be embedded in a class
Class serves as a namespace
>>> class User: ... def get_from_database(username): ... # some logic to get user from database ... result = ... ... if not result: ... raise self.DoesNotExist ... ... class DoesNotExist(Exception): ... pass
Usage:
>>> try: ... alice = User.get_from_database(username='apricot') ... except User.DoesNotExist: ... print('Error, user does not exist')
2.1.3. Exception Chain
>>> def login(username, password): ... raise RuntimeError('Cannot login') >>> >>> >>> try: ... login('apricot', 'secret') ... except RuntimeError as err: ... raise PermissionError('Invalid credentials') from err ... Traceback (most recent call last): RuntimeError: Cannot login The above exception was the direct cause of the following exception: Traceback (most recent call last): PermissionError: Invalid credentials
2.1.4. Exception Chain Silencing
>>> def login(username, password): ... raise RuntimeError('Cannot login') >>> >>> >>> try: ... login('apricot', 'secret') ... except RuntimeError as err: ... raise PermissionError('Invalid credentials') from None ... Traceback (most recent call last): PermissionError: Invalid credentials
2.1.5. Use Case - 1
>>> class InvalidCredentials(Exception): ... pass >>> >>> class User: ... def __init__(self, username, password): ... self.username = username ... self.password = password ... ... def login(self, username, password): ... if self.username != username or self.password != password: ... raise InvalidCredentials('Invalid username or password')
>>> Alice = User('apricot', 'secret') >>> >>> Alice.login('apricot', 'invalid') Traceback (most recent call last): InvalidCredentials: Invalid username or password
2.1.6. Use Case - 2
Django Framework Use-case of Custom Exceptions:
>>> # ... from django.contrib.auth.models import User >>> >>> >>> def login(request): ... username = request.POST.get('username') ... password = request.POST.get('password') ... ... try: ... user = User.objects.get(username, password) ... except User.DoesNotExist: ... print('Sorry, no such user in database')
2.1.7. Use Case - 3
Dragon
>>> class Dragon: ... def take_damage(self, damage): ... if damage >= 10: ... raise self.IsDead ... ... class IsDead(Exception): ... pass >>> >>> >>> wawelski = Dragon() >>> >>> try: ... wawelski.take_damage(100) ... except Dragon.IsDead: ... print('Dragon is dead') Dragon is dead
2.1.8. Assignments
# %% About # - Name: Syntax Exception Define # - Difficulty: easy # - Lines: 2 # - Minutes: 2 # %% 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. Define new exception `NegativeKelvinError` # 2. Run doctests - all must succeed # %% Polish # 1. Zdefiniuj nowy wyjątek `NegativeKelvinError` # 2. Uruchom doctesty - wszystkie muszą się powieść # %% Expected # >>> raise NegativeKelvinError() # Traceback (most recent call last): # NegativeKelvinError # # >>> raise NegativeKelvinError('Temperature below absolute zero') # Traceback (most recent call last): # NegativeKelvinError: Temperature below absolute zero # %% Hints # - `class` # - `pass` # %% Doctests """ >>> import sys; sys.tracebacklimit = 0 >>> assert sys.version_info >= (3, 9), \ 'Python has an is invalid version; expected: `3.9` or newer.' >>> from inspect import isclass >>> isclass(NegativeKelvinError) True >>> issubclass(NegativeKelvinError, Exception) True """ # %% Run # - PyCharm: right-click in the editor and `Run Doctest in ...` # - PyCharm: keyboard shortcut `Control + Shift + F10` # - Terminal: `python -m doctest -f -v myfile.py` # %% Imports # %% Types NegativeKelvinError: type[Exception] # %% Data # %% Result
# %% About # - Name: Syntax Exception Raise # - Difficulty: easy # - Lines: 2 # - Minutes: 2 # %% 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. Check value `value` passed to a `result` function # 2. If `value` is lower than 0, raise `NegativeKelvinError` # 3. Run doctests - all must succeed # %% Polish # 1. Sprawdź wartość `value` przekazaną do funkcji `result` # 2. Jeżeli `value` jest mniejsze niż 0, podnieś `NegativeKelvinError` # 3. Uruchom doctesty - wszystkie muszą się powieść # %% Expected # >>> result(1) # >>> # >>> result(0) # >>> # >>> result(-1) # Traceback (most recent call last): # NegativeKelvinError # %% Hints # - `raise` # - `if` # %% Doctests """ >>> import sys; sys.tracebacklimit = 0 >>> assert sys.version_info >= (3, 9), \ 'Python has an is invalid version; expected: `3.9` or newer.' >>> from inspect import isclass >>> isclass(NegativeKelvinError) True >>> issubclass(NegativeKelvinError, Exception) True >>> result(1) >>> result(0) >>> try: ... result(-1) ... except NegativeKelvinError: ... True True """ # %% Run # - PyCharm: right-click in the editor and `Run Doctest in ...` # - PyCharm: keyboard shortcut `Control + Shift + F10` # - Terminal: `python -m doctest -f -v myfile.py` # %% Imports # %% Types from typing import Callable result: Callable[[int], Exception] # %% Data class NegativeKelvinError(Exception): pass # %% Result def result(value): ...
# %% About # - Name: Syntax Exception Embed # - 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 `User` class # 2. Add new exception `DoesNotExist` inside `User` class # 3. Run doctests - all must succeed # %% Polish # 1. Zmodyfikuj klasę `User` # 2. Dodaj nowy wyjątek `DoesNotExist` wewnątrz klasy `User` # 3. Uruchom doctesty - wszystkie muszą się powieść # %% Expected # >>> raise User.DoesNotExist() # Traceback (most recent call last): # User.DoesNotExist # %% Hints # - `class` # - `pass` # %% Doctests """ >>> import sys; sys.tracebacklimit = 0 >>> assert sys.version_info >= (3, 9), \ 'Python has an is invalid version; expected: `3.9` or newer.' >>> from inspect import isclass >>> isclass(User.DoesNotExist) True >>> issubclass(User.DoesNotExist, Exception) True """ # %% Run # - PyCharm: right-click in the editor and `Run Doctest in ...` # - PyCharm: keyboard shortcut `Control + Shift + F10` # - Terminal: `python -m doctest -f -v myfile.py` # %% Imports # %% Types User: type DoesNotExist: type[Exception] # %% Data # %% Result class User: def __init__(self, username): self.username = username def __str__(self): return f"User('{self.username}')"
# %% About # - Name: Syntax Exception UserDoesNotExist # - 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 `login()` # 2. Check if combination of username and password exists in `DATA`: # - if yes: return `User` instance # - if not: raise `User.DoesNotExist` exception # 3. Run doctests - all must succeed # %% Polish # 1. Zmodyfikuj funkcję `login` # 2. Sprawdź czy kombinacja username i password występuje w `DATA`: # - jeżeli tak: zwróć instancję klasy `User` # - jeżeli nie: podnieś wyjątek `User.DoesNotExist` # 3. Uruchom doctesty - wszystkie muszą się powieść # %% Expected # >>> try: # ... user = login('alice', 'secret') # ... except User.DoesNotExist: # ... print('Invalid username and/or password') # ... else: # ... print('User login') # User login # # >>> try: # ... user = login('alice', 'invalid') # ... except User.DoesNotExist: # ... print('Invalid username and/or password') # ... else: # ... print('User login') # Invalid username and/or password # %% Hints # - `class` # - `pass` # %% Doctests """ >>> import sys; sys.tracebacklimit = 0 >>> assert sys.version_info >= (3, 9), \ 'Python has an is invalid version; expected: `3.9` or newer.' >>> from inspect import isclass >>> isclass(User.DoesNotExist) True >>> issubclass(User.DoesNotExist, Exception) True >>> try: ... user = login('alice', 'secret') ... except User.DoesNotExist: ... print('Invalid username and/or password') ... else: ... print('User login') User login >>> try: ... user = login('alice', 'invalid') ... except User.DoesNotExist: ... print('Invalid username and/or password') ... else: ... print('User login') Invalid username and/or password >>> try: ... user = login('bob', 'secret') ... except User.DoesNotExist: ... print('Invalid username and/or password') ... else: ... print('User login') Invalid username and/or password >>> try: ... user = login('bob', 'qwerty') ... except User.DoesNotExist: ... print('Invalid username and/or password') ... else: ... print('User login') User login """ # %% Run # - PyCharm: right-click in the editor and `Run Doctest in ...` # - PyCharm: keyboard shortcut `Control + Shift + F10` # - Terminal: `python -m doctest -f -v myfile.py` # %% Imports # %% Types from typing import Callable User: type login: Callable[[str, str], object|Exception] # %% Data DATA = [ {'username': 'alice', 'password': 'secret'}, {'username': 'bob', 'password': 'qwerty'}, {'username': 'carol', 'password': '123456'}, {'username': 'dave', 'password': 'abc123'}, {'username': 'eve', 'password': 'password1'}, {'username': 'mallory', 'password': 'NULL'}, ] class User: def __init__(self, username): self.username = username def __str__(self): return f"User('{self.username}')" class DoesNotExist(Exception): pass # %% Result def login(username, password): ...
# %% About # - Name: Syntax Exception IsDead # - 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 `Hero` class # 2. Add new exception `IsDead` inside `Hero` class # 3. Modify `take_damage` method # 4. If `health` is equal or lower than 0, raise `IsDead` # 5. Run doctests - all must succeed # %% Polish # 1. Zmodyfikuj klasę `Hero` # 2. Dodaj nowy wyjątek `IsDead` wewnątrz klasy `Hero` # 3. Zmodyfikuj metodę `take_damage` # 4. Jeżeli `health` jest równy lub mniejszy niż 0, podnieś `IsDead` # 5. Uruchom doctesty - wszystkie muszą się powieść # %% Expected # >>> hero = Hero('Alice') # >>> hero.take_damage(1) # >>> # >>> try: # ... hero.take_damage(20) # ... except hero.IsDead: # ... True # True # %% Hints # - `class` # - `pass` # - `raise` # - `if` # %% Doctests """ >>> import sys; sys.tracebacklimit = 0 >>> assert sys.version_info >= (3, 9), \ 'Python has an is invalid version; expected: `3.9` or newer.' >>> from inspect import isclass >>> isclass(Hero.IsDead) True >>> issubclass(Hero.IsDead, Exception) True >>> hero = Hero('Alice') >>> hero.take_damage(1) >>> try: ... hero.take_damage(20) ... except hero.IsDead: ... True True """ # %% Run # - PyCharm: right-click in the editor and `Run Doctest in ...` # - PyCharm: keyboard shortcut `Control + Shift + F10` # - Terminal: `python -m doctest -f -v myfile.py` # %% Imports # %% Types Hero: type # %% Data # %% Result class Hero: def __init__(self, name): self.name = name self.health = 10 def take_damage(self, damage): self.health -= damage