Python3 Errors Execptions
# Python3 Errors and Exceptions
As a Python beginner, when you first start learning Python programming, you will often encounter some error messages. We haven't mentioned them before, but this chapter will introduce them specifically.
Python has two types of errors that are easy to identify: syntax errors and exceptions.
Python's `assert` (assertion) is used to evaluate an expression and triggers an exception when the expression condition is `false`.
!(https://static.jyshare.com/images/mix/assets-py.webp)
## Syntax Errors
Python's syntax errors, also known as parsing errors, are common for beginners. For example:
```python
>>> while True print('Hello world')
File "", line 1, in ?
while True print('Hello world')
^
SyntaxError: invalid syntax
In this example, the function `print()` is found to have an error because it is missing a colon `:` before it.
The parser points out the line with the error and marks the earliest position where the error was found with a small arrow.
## Exceptions
Even if a Python program's syntax is correct, errors may still occur when it is run. Errors detected during runtime are called exceptions.
Most exceptions are not handled by the program and are displayed here in the form of error messages:
## Example
```python
>>> 10 * (1/0) # 0 cannot be used as a divisor, triggers an exception
Traceback (most recent call last):
File "", line 1, in ?
ZeroDivisionError: division by zero
>>> 4 + spam*3 # spam is undefined, triggers an exception
Traceback (most recent call last):
File "", line 1, in ?
NameError: name 'spam' is not defined
>>> '2' + 2 # int cannot be added to str, triggers an exception
Traceback (most recent call last):
File "", line 1, in
TypeError: can only concatenate str (not "int") to str
Exceptions appear in different types, and these types are printed as part of the information. The types in the examples are `ZeroDivisionError`, `NameError`, and `TypeError`.
The front part of the error message shows the context in which the exception occurred and displays specific information in the form of a call stack.
## Exception Handling
### try/except
Exception catching can be done using `try/except` statements.
!(#)
In the following example, the user is asked to enter a valid integer, but the user is allowed to interrupt the program (using Control-C or the method provided by the operating system). The user interruption message will raise a `KeyboardInterrupt` exception.
```python
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("That's not a valid number. Please try again!")
The `try` statement works as follows:
* First, the `try` clause (the statement between the keywords `try` and `except`) is executed.
* If no exception occurs, the `except` clause is skipped, and the `try` clause execution is complete.
* If an exception occurs during the execution of the `try` clause, the rest of the clause is skipped. If the exception type matches the name after `except`, the corresponding `except` clause is executed.
* If an exception does not match any `except`, it is passed to the outer `try` statement.
A `try` statement may contain multiple `except` clauses to handle different specific exceptions. At most one branch will be executed.
The handler will only handle exceptions in the corresponding `try` clause, not exceptions in other `try` handlers.
An `except` clause can handle multiple exceptions at once. These exceptions are placed in parentheses as a tuple, for example:
```python
except (RuntimeError, TypeError, NameError):
pass
The last `except` clause can omit the exception name; it is used as a wildcard. You can use this method to print an error message and then re-raise the exception.
```python
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info())
raise
### try/except...else
The `try/except` statement also has an optional **else** clause. If used, it must be placed after all `except` clauses.
The `else` clause is executed when no exception occurs in the `try` clause.
!(#)
The following example checks if a file can be opened in the `try` statement. If the file opens normally without an exception, the `else` part is executed to read the file contents:
```python
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
Using the `else` clause is better than putting all statements inside the `try` clause, as it avoids catching unexpected exceptions that `except` cannot handle.
Exception handling not only deals with exceptions that occur directly in the `try` clause but also handles exceptions raised in functions called within the clause (even indirectly). For example:
```python
>>> def this_fails():
x = 1/0
>>> try:
this_fails()
except ZeroDivisionError as err:
print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero
### try-finally Statement
The `try-finally` statement executes the final code regardless of whether an exception occurs.
!(#)
In the following example, the `finally` statement is executed whether an exception occurs or not:
## Example
```python
try:
()
except AssertionError as error:
print(error)
else:
try:
with open('file.log') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
finally:
print('This statement is executed regardless of whether an exception occurs.')
* * *
## Raising Exceptions
Python uses the `raise` statement to raise a specified exception.
The syntax for `raise` is as follows:
```python
raise [Exception [, args [, traceback]]]
!(#)
The following example raises an exception if `x` is greater than 5:
```python
x = 10
if x > 5:
raise Exception('x cannot be greater than 5. The value of x is: {}'.format(x))
Executing the above code will raise an exception:
Traceback (most recent call last):
File "test.py", line 3, in
raise Exception('x cannot be greater than 5. The value of x is: {}'.format(x))
Exception: x cannot be greater than 5. The value of x is: 10
The sole argument to `raise` specifies the exception to be raised. It must be an exception instance or an exception class (i.e., a subclass of `Exception`).
If you only want to know whether an exception was raised without handling it, a simple `raise` statement can re-raise it.
```python
>>> try:
raise NameError('HiThere') # Simulate an exception.
except NameError:
print('An exception flew by!')
raise
An exception flew by!
Traceback (most recent call last):
File "", line 2, in ?
NameError: HiThere
* * *
## User-Defined Exceptions
You can create your own exceptions by creating a new exception class. Exception classes inherit from the `Exception` class, either directly or indirectly. For example:
```python
>>> class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "", line 1, in ?
__main__.MyError: 'oops!'
In this example, the default `__init__()` of the `Exception` class is overridden.
When creating a module that may raise multiple different exceptions, a common practice is to create a base exception class for the package and then create different subclasses for different error conditions based on this base class:
```python
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
Most exception names end with "Error," similar to the naming of standard exceptions.
* * *
## Defining Cleanup Actions
The `try` statement has another optional clause that defines cleanup actions that are executed under any circumstances. For example:
```python
>>> try:
raise KeyboardInterrupt
finally:
print('Goodbye, world!')
Goodbye, world!
Traceback (most recent call last):
File "", line 2, in
KeyboardInterrupt
In the above example, the `finally` clause is executed regardless of whether an exception occurs in the `try` clause.
If an exception is raised in the `try` clause (or in the `except` and `else` clauses) and is not caught by any `except`, the exception is re-raised after the `finally` clause is executed.
Here is a more complex example (containing both `except` and `finally` clauses in the same `try` statement):
```python
>>> def divide(x, y):
try:
result = x / y
except ZeroDivisionError:
print("division by zero!")
else:
print("result is", result)
finally:
print("executing finally clause")
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
File "", line 1, in ?
File "", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'
* * *
## Predefined Cleanup Actions
Some objects define standard cleanup actions that are executed once they are no longer needed, regardless of whether the system successfully used them.
The following example shows attempting to open a file and then printing its contents to the screen:
```python
for line in open("myfile.txt"):
print(line, end="")
The problem with this code is that after execution, the file remains open and is not closed.
The `with` keyword statement ensures that objects like files are properly cleaned up after use:
```python
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 a problem occurs during processing.
For more information on the `with` keyword, see: (#)
* * *
## Related Content
[Python assert (Assertion)](#)
(#)
YouTip