In this tutorial, we will see what exceptions are and how to manage them in MicroPython to handle errors in our code.3
An exception is an event that occurs during the execution of a program and interrupts the normal flow of instructions.
These situations can be caused by errors in the code, unexpected conditions in the hardware, or problems with the input data.
In MicroPython, exceptions are objects that represent these errors. When an exception occurs, the program stops unless the exception is caught and handled.
If you want to learn more, check out,
Basic Structure of Exception Handling
In MicroPython, exception handling is done using try
and except
blocks. The basic structure is as follows:
try:
# Code that may raise an exception
result = divide(10, 0)
except ZeroDivisionError:
# Code that runs if a ZeroDivisionError occurs
print("Error: Cannot divide by zero.")
Here we place the code that may raise an exception. If an exception occurs within this block, the program flow diverts to the except
block.
Here we handle the exception. We can specify the type of exception we want to catch (e.g., ZeroDivisionError
) or use a generic except
to catch any exception.
This block runs if no exception is raised in the try
block.
This block always runs, regardless of whether an exception was raised or not. It is useful for releasing resources or performing cleanup tasks.
Let’s see this with a complete example that includes the try
, except
, else
, and finally
blocks:
try:
result = divide(10, 2) # This will not raise an exception
except ZeroDivisionError:
print("Error: Cannot divide by zero.")
else:
print(f"The result is: {result}")
finally:
print("End of the try-except block.")
In this example, since no exception is raised, the else
and finally
blocks execute.
We can also catch multiple types of exceptions in a single try-except
block:
try:
value = int("not a number") # This will raise a ValueError
except ValueError:
print("Error: Invalid value.")
except TypeError:
print("Error: Incorrect data type.")
Common Types of Exceptions in MicroPython
MicroPython defines several types of exceptions that we can catch and handle. Some of the most common are:
Error | Description |
---|---|
ZeroDivisionError | Occurs when trying to divide by zero. |
TypeError | Occurs when an operation is performed with incompatible data types. |
ValueError | Occurs when an inappropriate value is passed to a function. |
IndexError | Occurs when trying to access an index out of the bounds of a list or array. |
NameError | Occurs when trying to use a variable or function that is not defined. |
OSError | Occurs in operations related to the file system or I/O (e.g., trying to open a file that does not exist). |
Practical Examples
User Input Validation
This example shows how to handle invalid user input:
try:
age = int(input("Enter your age: "))
except ValueError:
print("Error: You must enter a valid number.")
else:
if age >= 18:
print("You are an adult.")
else:
print("You are a minor.")
File Management
In this example, the file is always closed, regardless of whether an exception occurred or not.
try:
file = open("data.txt", "r")
content = file.read()
except OSError as e:
print(f"Error opening the file: {e}")
else:
print("File read successfully.")
finally:
if 'file' in locals():
file.close()
print("File closed.")
Error Handling in Hardware Operations
In embedded devices, it is common to work with sensors and actuators. Here’s how to handle errors when reading a sensor:
from machine import Pin, ADC
sensor = ADC(Pin(34))
try:
value = sensor.read()
except OSError as e:
print(f"Error reading the sensor: {e}")
else:
print(f"Sensor value: {value}")
Exception Handling in I2C Communications
When working with I2C devices, communication errors may occur. Here’s how to handle them:
from machine import I2C, Pin
i2c = I2C(scl=Pin(22), sda=Pin(21))
try:
devices = i2c.scan()
except OSError as e:
print(f"I2C communication error: {e}")
else:
print(f"Devices found: {devices}")