Python Book
πŸ‡ΊπŸ‡¦ Stand with UkraineπŸŽ“Training Suite
  • Book overview
  • Notes about this book
  • 1. Introduction to Python
    • What is Python
    • Basic syntax
    • Objects in Python
    • Python overview
    • Installation, IDEs etc.
    • ipython
    • Sources for self-learning
  • 2. Strings and numbers
    • Getting help
    • Introspection
    • Basic types
    • None object
    • Numbers
    • Strings
    • Unicode
    • String Formatting
    • Regular expressions
    • Sources for self-learning
  • 3. Containers
    • Data Structures
    • Lists
    • Tuples
    • Dictionaries
    • Sets
    • Conditions
    • Loops
    • Additional modules
    • Sources for self-learning
  • 4. Functions
    • Functions
    • Scopes of visibility
    • Generators
    • Lambdas
    • Type hints
    • Function internals
    • Sources for self-learning
  • 5. Functional Programming
    • Builtins
    • Iterable
    • Iterator
    • Functional Programming
    • Functools
    • Comprehensions
    • Additional modules
    • Sources for self-learning
  • 6. Code Styling
    • Zen of Python
    • Lint
    • PEP 8
    • Modules
    • Packages
    • Sources for self-learning
  • 7. OOP
    • OOP Basics
    • Code design principles
    • Classes
    • Method Resolution Order
    • Magic attributes and methods
    • Super
    • Sources for self-learning
  • 8. Decorators, Exceptions
    • Decorators
    • Exceptions
    • Sources for self-learning
  • 9. Testing
    • Basic Terminology
    • Testing theory
    • Dev unit testing vs QA automated testing
    • Best Practices
    • Doctest
    • Unittest
    • Test Runners
    • Pytest
    • Nose
    • Continuous Integration
  • 10. System Libs
    • Working with files
    • System libraries
    • Subprocess
    • Additional CLI libraries
Powered by GitBook
On this page
  • Custom Exceptions
  • Referring to exceptions
  • Catching multiple exceptions

Was this helpful?

Edit on Git
  1. 8. Decorators, Exceptions

Exceptions

Errors detected during execution are called exceptions and are not unconditionally fatal

  • It is Pythonic way to use them as much often as possible

  • Sometimes you can't predict all possible values and situations

    • No heaps of if else conditions

General form:

try:
    <code> 
except <ExceptionName> as <alias>:
    <code in case of error happened>
else: 
    <code if everything was OK>
finally: 
    <code in any case>

We are checking the code only after try before except.

πŸͺ„ Code:

def divide_ten(num): 
    try: 
        print(10.0 / float(num))
    except ZeroDivisionError as e: 
        print(f"Oops, invalid - you can't pass 0. Error: {e}") 
    except TypeError:
        print("Wrong type!", type(num))
    except Exception as e:
        print("Unexpected exception:", e)
    else: 
        print("Cool, no exceptions were triggered!") 
    finally: 
        print("We're done with that.")

print("1)")        
divide_ten("2") 
print("2)")
divide_ten(0)
print("3)")
divide_ten([3])

πŸ“Ÿ Output:

1)
5.0
Cool, no exceptions were triggered!
We're done with that.
2)
Oops, invalid - you can't pass 0. Error: float division by zero
We're done with that.
3)
Wrong type! <class 'list'>
We're done with that.

Another working example:

Checking user's input and returning the list item. Non-ideal solution would be:

πŸͺ„ Code:

l = list(range(10))

def get_item():
    num = input("Enter index: ")
    # Fix this example!!!
    if not num.isdigit() or (num.startswith("-") and not num[1:].isdigit()):
        return "Incorrect value"
    if len(l) < int(num):
        return "Out of range"
    return l[int(num)]

get_item()

πŸ“Ÿ Output:

Enter index: -5





'Incorrect value'

Better solution:

def get_item():
    num = input("Enter index: ")
    try:
        return l[int(num)]
    except IndexError:
        return "Out of range"
    except (TypeError, ValueError):
        return "Incorrect value"
    except Exception as e:
        return f"Unexpected exception: {e.__class__.__name__}({e})"

Custom Exceptions

class SimpleCustomException(Exception):
    pass

class CustomException(Exception): 
    def __init__(self, value="Some error"): 
        self.parameter = value 
        
    def __str__(self): 
        return self.parameter

For raising custom Exception – raise used:

  • raise CustomException

  • raise CustomException()

πŸͺ„ Code:

# divide.py :
class NegativeException(Exception): 
    def __init__(self, message="Can't work with negative numbers"):
        #logger.error("...")
        self.message = message
    
    def __str__(self):
        return "ERROR: " + self.message

def divide_ten(num):
    if num < 0:
        raise NegativeException
    return 10.0 / num

#========================
# from divide import divide_ten, NegativeException

def main(num):
    try:
        print(
            divide_ten(num)
        )
    except ZeroDivisionError:
        print("Oops, can't div by zero!")
    except NegativeException as e:
        print(e) 

main(0)
main(-6)
main(3)

πŸ“Ÿ Output:

Oops, can't div by zero!
ERROR: Can't work with negative numbers
3.3333333333333335

Referring to exceptions

Please note that raise can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):

πŸͺ„ Code:

import sys

try:
    f = open('/tmp/1123123.txt')
    s = f.readline()
    i = int(s.strip())
except TypeError:
    print("Wrong type")
except ValueError as e:
    print(f"Could not convert data to an integer: {e}")
except OSError as err: 
    print("OS error: {}".format(err))
    print(err.filename)
except:
    print("Unexpected error:", sys.exc_info())
    raise

πŸ“Ÿ Output:

OS error: [Errno 2] No such file or directory: '/tmp/1123123.txt'
/tmp/1123123.txt

Catching multiple exceptions

  • Several except blocks

  • Putting several exceptions in a tuple

πŸͺ„ Code:

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except (IOError, ValueError) as e: 
    print(f"Data or file error: {e}")

πŸ“Ÿ Output:

Data or file error: [Errno 2] No such file or directory: 'myfile.txt'

## assert

Testing for poor ones

Debug version of raise with condition:

assert <test>[, <data>]

is equivalent to:

if __debug__: 
    if not <test>: 
        raise AssertionError(<data>)

__debug__ is special bool variable (interpreter-level constant (one of very few ones!)) which allways is True unless python is called with -O (optimization, capital O – not a zero!)

python –O script.py

Examples of assert:

πŸͺ„ Code:

assert 1 == 1
assert len(range(5)) == 5
try:
    assert 2 + 2 == "2 + 2", "On paper it works..."
except AssertionError as e:
    print("Cought AssertionError:", e)
Cought AssertionError: On paper it works...
PreviousDecoratorsNextSources for self-learning

Last updated 2 years ago

Was this helpful?