Python101: 16. Errors and Exceptions

post thumb
Python
by Admin/ on 14 Jul 2021

Python101: 16. Errors and Exceptions


As a Python beginner, when you first learn Python programming, you will often see error messages, which are the errors and exceptions we’ll talk about next.

When we execute program statements, we often see error messages reported on the command line output, such as

>>> while True print('Hello world')
  File "<stdin>", line 1, in ?
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

Such error messages prevent the program from running properly, which are the errors and exceptions we will introduce.

Error


By errors we mean Python syntax errors, e.g.

>>> if 1=1: print('always')
  File "<stdin>", line 1
    if 1=1: print('always')
        ^
SyntaxError: invalid syntax

In the above example, ‘'==’ should be used instead of ‘=’ when determining equality. When executed, the syntax parser checks that there is an error, the program statement terminates execution and the error is pointed out with an up arrow.

Syntax errors are easily solved by checking the syntax and correcting it according to the location of the error prompted on the command line.

Exceptions


In Python, even if your code has no syntax errors, there is no guarantee that the program will finish running the way you want it to, because there will be errors during program execution as well. Errors detected during program execution are called exceptions, e.g.

>> '1' + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: Can't convert 'int' object to str implicitly

Most of the exceptions are not handled by the program and are displayed as error messages, as shown in the example above, where the prompt tells us that the int type cannot be added to the str type.

The error message will tell us the context in which the exception occurred and display the specific information in the form of a call stack. The last line of the message will start with the name of the error type, in the above example, the error type is ‘TypeError’, indicating a type exception.

What is an exception

An exception is an event that occurs during program execution and thus affects the normal execution of the program. When Python encounters a program that it cannot handle, it raises an exception. In Python, an exception is an object that represents an error that we need to catch and handle when an exception occurs in a Python script, otherwise the program will terminate execution.

Handling exceptions

Python provides try/except statements to catch and handle exceptions. try statements are used to detect errors in blocks of statements, except statements are used to catch exceptions in try statements and handle them, and additional else statements can be executed when there are no exceptions in try statements.

Syntax

The following is the simplest try… .except… .else as an example.

try:
    statement(s) # Block of statements to test
except exception.
    deal_exception_code # If an 'exception' is raised in the try section
except exception2, e:
    deal_exception2_code # If the 'exception2' exception was raised
else:
    no_exception_happend_code # if no exception was raised

The execution logic of the try statement is as follows.

  • First, the try clause (the (multi-line) statement between the try and except keywords) is executed.
  • If no exceptions occur, the except clause is skipped and the execution of the try statement is completed.
  • If an exception occurs during the execution of the try clause, the rest of the clause is skipped. Then, if the type of the exception matches the exception following the except keyword, the except clause is executed, and the code continues after the try statement.
  • If an exception occurs that does not match the exception specified in the except clause, it is passed to the outer try statement; if no handler is found, it is an unhandled exception and execution stops with an error message.
  • If the try statement executes without an exception, the statement after the else statement (if there is an else) is executed, and then control flows through the entire try statement.

base class

An exception is compatible with the class in the except clause if the class in which it occurs and the class in the except clause are the same class or its base class (but the converse is not true - the except clause listing the derived class is compatible with the base class).

Example
class BException(Exception): #Inherit Exception base class
    pass

class CException(BException): #Inherit BException base class
    pass

class DException(CException): #Inherit CException base class
    pass

for cls in [BException, CException, DException]:
    try:
        raise cls() #Throw exception
    except DException:
        print("D")
    except CException:
        print("C")
    except BException:
        print("B")

# output
# B
# C
# D

Note that if the except clause is reversed (putting except BException first), it will print B, B, B — since the DException class inherits from the CException class and the CException class inherits from the BException class, putting except BException first will match the three exceptions, and the following excepts will not be executed.

without exception type except

Python can end all excepts with an except clause, which can omit the exception name to be used as a wildcard. It can catch all exceptions that are not caught by any of the preceding excepts (if any).

try:
    statement(s) # Block of statements to test
except exception.
    deal_exception_code # If an 'exception' is raised in the try section
except :
    deal_all_other_exception2_code # deal with all other exceptions
else:
    no_exception_happend_code # if no exceptions are raised
Example
try:
    raise BException() #Throw exception
except DException:
    print("D")
except:
    print("Handling all other exceptions") #Handle all other exceptions

# Output
# Handle all other exceptions

except statement catches multiple exception types

A try statement may have multiple except clauses to specify handlers for different exceptions, and at most one handler will be executed. Handlers handle only the exceptions that occur in the corresponding try clause, not the exceptions in other handlers within the same try statement. An except clause can name multiple exceptions as a tuple with parentheses.

try:
    statement(s) # Block of statements to test
except exception.
    deal_exception_code # If an 'exception' is raised in the try section
except (Exception1[, Exception2[,... . ExceptionN]]]) :
    deal_all_other_exception2_code # Handle multiple exceptions
else:
    no_exception_happend_code # if no exceptions occur
Example
try:
    raise BException() #Throw exception
except (BException, DException):
    print("D")
except:
    print("Handling all other exceptions") #Handle all other exceptions
else:
    print("No exceptions occurred") # No exceptions occurred

#output
# D

try - finally statements

The finally statement is used to execute the final code regardless of whether an exception occurs.

try:
    # <statement>
finally:
    # <statement> # always executed when exiting try
Example
try:
    raise BException() #Throw exception
except (BException, DException):
    print("D")
except:
    print("Handling all other exceptions") #Handle all other exceptions
else:
    print("No exceptions occurred") # No exceptions occurred
finally:
    print("You can't get around me, you have to execute") #Code that must be executed


    
#output
# D
# You can't get around me, you have to execute

Note the difference between finally and else. Finally is executed regardless of exceptions, while else is executed only if there are no exceptions. That is, if there is no exception, then both finally and else will be executed.

Parameters of the #### exception

The except clause can specify a variable after the exception name. This variable is bound to an exception instance, whose arguments are a tuple, usually containing the error string, error number, and error location, stored in .args. For convenience, the exception instance defines str(), so that the arguments can be printed directly without referring to .args.

try:
    # Normal operation ......
except ExceptionType as inst:
    # You can output the value of inst here .....
Example
try:
    x = 1 / 0 # Divide by 0
except ZeroDivisionError as err: # Specify the variable err for the exception
    print("Exception")
    print(err.args) # Print the tuple of arguments for the exception
    print(err) # print the arguments, since __str__() is defined

#output
# Exception
# ('division by zero',)
# division by zero

Trigger exception

Python provides the raise statement to manually raise an exception.

Syntax
raise [Exception [, args [, traceback]]]
Parameter Description
Exception: type of the exception, e.g. ZeroDivisionError
args: the value of the exception argument, optional, default value "None"
traceback: optional, used to set whether to trace the exception object

The exception parameter value can be a string, class or object

Example
def diyException(level):
    if level > 0:
        raise Exception("raise exception", level) #Throw an exception proactively and with arguments
        print('I am not going to execute') #This line of code will not be executed

try:
   diyException(2) #Execute the exception method
except Exception as err: #Catch the exception
    print(err) #Print the exception parameter


    
# Output
# ('raise exception', 2)

In order to catch an exception, the “except” statement must throw a class object or string with the same exception. To catch the exception thrown by the above code, the except statement should look like this.

#Define the function
def diyException(level):
    if level > 0:
        raise Exception("error level", level) #Throw an active exception with arguments
        print('I am not going to execute') #This line of code will not be executed

try:
   diyException(2) #Execute the exception method
except 'error level' as err: #Catch the exception
    print(err) #Print the exception parameter

#output
# Traceback (most recent call last):
#   File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>
#     diyException(2) #Execute the exception method
#   File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
#     raise Exception("error level", level) #Throw an active exception with parameters
# Exception: ('error level', 2)

Of course, we can also catch exceptions via traceback: the

import traceback

#Define the function
def diyException(level):
    if level > 0:
        raise Exception("error level", level) #Throw an active exception with arguments
        print('I am not going to execute') #This line of code will not be executed

try:
   diyException(2) #Execute the exception method
except Exception: #Catch the exception
    traceback.print_exc()

#output
# Traceback (most recent call last):
#   File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 51, in <module>
#     diyException(2) #Execute the exception method
#   File "/Users/cxhuan/Documents/python_workspace/stock/test.py", line 47, in diyException
#     raise Exception("error level", level) #Throw an active exception with parameters
# Exception: ('error level', 2)

User-defined exceptions

In addition to using Python’s built-in exceptions, we can create our own exception types. Creating your own exceptions is as simple as creating a class and inheriting from the Exception class or its subclasses.

The following code creates an exception DiyError inherits from Python’s built-in RuntimeError and is used to output more information when an exception is raised.

#CustomException
class DiyError(RuntimeError):
    def __init__(self, arg):
        self.args = arg

try:
    raise DiyError("my diy exception") # Trigger exception
except DiyError as e:
    print(e)

Once defined, we can use the DiyError exception after the except statement, where the variable e is used to create an instance of the DiyError class. We can also trigger this exception manually with a raise statement.

Predefined cleanup actions

Some objects define a standard cleanup behavior that is executed once it is no longer needed, regardless of whether the system has successfully used it.

for line in open("myfile.txt"):
    print(line, end="")

The above example tries to open a file and then print out the contents. But there is a problem: when the execution is finished, the program does not close the file stream and the file stays open.

The keyword with statement ensures that an object such as a file will be cleaned up correctly after it is used.

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

After the above code is executed, the file f will always be closed even if something goes wrong during processing. The principle here is the use of the finally mechanism, so if you are interested, you can go deeper into it.

Summary


This section gives an introduction to the use of Python errors and exceptions. Mastering error and exception handling can greatly improve the robustness of your program and provide a guarantee that your program will continue to run completely.


Reference

https://github.com/JustDoPython/python-100-day/tree/master/day-011

comments powered by Disqus