python exception assertion - ghdrako/doc_snipets GitHub Wiki

There are 64 build-in exception. it's three shape hierarchy.

General exception can handle a raised exception as long as is matches coverage, concrete exception is not reqired.

try:
  1/0
except AritmeticError:   # ZeroDivisionError
  ...

obraz

try:
  # code that might raise an exception
except Exception as e:
  # code that executes if an exception occurs
else:
  # code that executes if no exception occurs (optional)
finally:
  # code that executes whether an exception occurs or not (optional)
try:
  print(5/0)
except ZeroDivisionError:
  print("You can't divide by zero!")
try:
  1 / 0
except ZeroDivisionError as ex:
  print(f"Type: {type(ex)}")
print(f"Is an instance of ZeroDivisionError? {isinstance(ex, ZeroDivisionError)}")

Raising exception

The rise instruction raises the specified exception as if it was rised in normal(natural) way.

try:
  rise ZeroDivisionError

except AritmeticError:
  ...
def range_check_user_input(value):
  if not 0 < value <= 100:
    raise ValueError("value range exceeded", value)
  # additional functionality

def get_data_from_user():
  # initialization and gather user input
  try:
    range_check_user_input(value)
  except ValueError as e:
    print(e)
  # restart code to get user input

To supply a custom message to the exception, we use the format raise ExceptionClass("custom message") . A few examples follow:

raise ValueError("Please use the correct parameter.")
# ERROR: ValueError: Please use the correct parameter.
code_used = "3#"
raise ValueError(f"You used a wrong parameter: {code_used!r}")
# ERROR: ValueError: You used a wrong parameter: '3#'

Re-rise exception

Empty rise can only be used in except block. In folowing code ZeroDivisionError is rised twice.

def division(n):
  try:
    return 0/n
  except:
    print('error')
    raise
try:
  division(1)
except AritmeticError:
  print("not ok")


Output:
error
not ok

Handle multiple exception

try:
  ...
except ZeroDivisionError as e:
  print(e)
  print(type(e))
except IndexError  as e:
  print(e)
  print(type(e))
try:
  ...
except (ZeroDivisionError, IndexError) as e:
  print(e)
  print(type(e))

Assertion

import math
data = float(input("Enter number:"))
assert data > 2.0                       # this rise AssertionError if condition is not true
x = math.sqrt(data)
print(x)

All assert statements will actually be removed from your code automatically when the interpreter is run with the -O or -OO flags to optimize the bytecode.

Asserts in Python are mainly meant to be used in tests and only during development phase just to ensure that things are not deviating from what is being expected e.g. that functions return sane values and that state variables do not contradict each other, and similar conditions. Also asserts are meant to fail early (in the spot where the error was detected) and thus AssertErrors are not really meant to be captured or handled programmatically.

else

def access(val):
  try:
    element=[1,2,3]
    element[val]
  except IndexError:
    print("Index error")
    return val
  else:
    print("ok")
    return  val

print(acces(0))
print(acces(5))

Import exception

try
  import file
except ImportError IE:
  print(IE.name)
  print(IE.path)

Encoding exception

try:
  b'\x99'.decode("utf-8")
except UnicodeError as UE:
  print(UE.encoding) # utf-8
  print(UE.reason)  # invalid start byte
  print(UE.object)  # b'\x99'
  print(UE.start)   # 0
  print(UE.end)     # 1

Chained exceptions

  • __context__
  • __casuse__
data=['first',2]

try:
  print(data[2]
except Exception as EX:
  try:
    print(1/0)
  except ZeroDivisionError as Z:
    print(EX)
    print(Z)
    print(Z.__context__)
    print(Z.__cause__)

__traceback__

Defining custom exception classes

class FileExtensionError(TaskierError):
  def __init__(self, file_path):
    super().__init__()
    self.file_path = file_path
  def __str__(self):
    return f"The file ({self.file_path}) doesn't appear to be a CSV file."
# In another part of our package
from pathlib import Path
def upload_file(file_path):
  path = Path(file_path)
  if path.suffix.lower() != ".csv":
    raise FileExtensionError(file_path)
  else:
    print(f"Processing the file at {file_path}")
class MyException(Exception):
  def __init__(self,msg):
    self.message = msg

balance = 1000
def insufficientBalance(withdrawal_amount):
  if withdrawal_amount <= balance:
    print('withdrawal successful')
  else:
    rise MyException('Widrawal amount is greater then balance')
amount = int(input('Enter the widrawal amount:')
try:
  insufficientBalance(amount)
exception MyException as obj:
  print(obj)

logging exception message

Logging an exception in python with an error can be done in the logging.exception() method. This function logs a message with level ERROR on this logger. The arguments are interpreted as for debug(). Exception info is added to the logging message. This method should only be called from an exception handler.

import logging
 
try:
    printf("GeeksforGeeks")
except Exception as Argument:
    logging.exception("Error occurred while printing GeeksforGeeks")
try:
    main_loop()
except Exception:
    logger.exception("Fatal error in main loop")

By default, logger.exception uses the log level of ERROR. Alternatively, you can use the regular logging methods— logger.debug(), logger.info(), logger.warn(), etc.—and pass the exc_info parameter, setting it to True:

while True:
    try:
        main_loop()
    except Exception:
        logger.error("Fatal error in main loop", exc_info=True)

Setting exc_info to True will cause the logging to include the full stack trace…. exactly like logger.exception() does. The only difference is that you can easily change the log level to something other than error: Just replace logger.error with logger.warn, for example.