smbus2
smbus2 is a pure Python implementation of the `python-smbus` package, designed as a drop-in replacement for `smbus-cffi` or `smbus-python`. It provides an interface for I2C and SMBus communication on Linux-based systems, offering enhanced features like SMBus Packet Error Checking (PEC), support for context managers for robust resource handling, and improved error management. Actively maintained, the library is currently at version 0.6.1, with a regular release cadence addressing bug fixes and minor improvements, making it a recommended choice for embedded I2C communication, particularly on platforms like Raspberry Pi.
Warnings
- breaking The `SMBusWrapper` class was removed in version 0.4.0. Direct instantiation of `SMBus` should be used instead.
- gotcha Frequent consecutive block read/write operations, especially on Raspberry Pi Zero W, can lead to `[Errno 121] Remote I/O error`. This often indicates bus congestion or timing issues.
- breaking Version 0.6.0 fixed a buffer overflow issue that could occur when using Python 3.14 on 64-bit systems.
- deprecated Testing for Python 2.7, 3.4, and 3.5 was officially dropped in version 0.4.3. While the code might still function, these versions are no longer actively supported or tested.
- gotcha smbus2 is not a literal 'drop-in replacement' in terms of import statements for the original `smbus` (or `python-smbus`). Attempting `import smbus` when only `smbus2` is installed will result in a `ModuleNotFoundError`.
- gotcha The `force` parameter in many I2C/SMBus functions (e.g., `read_byte_data`) instructs the Linux kernel to reuse a slave address even if it's already in use by a driver. This can mask underlying hardware or driver configuration issues and should be used cautiously.
Install
-
pip install smbus2
Imports
- SMBus
from smbus2 import SMBus
- SMBusWrapper
from smbus2 import SMBus
- i2c_msg
from smbus2 import i2c_msg
Quickstart
import os
from smbus2 import SMBus
# Example: Read a byte from an I2C device (e.g., at address 0x27, register 0x00)
# Replace `1` with the correct I2C bus number for your system (e.g., 0 for older Raspberry Pis, 1 for newer)
# Replace `0x27` with your device's I2C address
# Replace `0x00` with the register to read from
I2C_BUS_NUMBER = int(os.environ.get('I2C_BUS_NUMBER', '1')) # Default to bus 1
DEVICE_ADDRESS = int(os.environ.get('I2C_DEVICE_ADDRESS', '0x27'), 16)
REGISTER_ADDRESS = int(os.environ.get('I2C_REGISTER_ADDRESS', '0x00'), 16)
try:
# Using 'with' statement ensures the bus is properly closed
with SMBus(I2C_BUS_NUMBER) as bus:
byte_data = bus.read_byte_data(DEVICE_ADDRESS, REGISTER_ADDRESS)
print(f"Read byte 0x{byte_data:02X} from device 0x{DEVICE_ADDRESS:02X}, register 0x{REGISTER_ADDRESS:02X} on bus {I2C_BUS_NUMBER}.")
# Example: Write a byte to the same device/register
write_value = 0xAA # Example value to write
bus.write_byte_data(DEVICE_ADDRESS, REGISTER_ADDRESS, write_value)
print(f"Written byte 0x{write_value:02X} to device 0x{DEVICE_ADDRESS:02X}, register 0x{REGISTER_ADDRESS:02X} on bus {I2C_BUS_NUMBER}.")
except FileNotFoundError:
print(f"Error: I2C bus {I2C_BUS_NUMBER} not found. Ensure I2C is enabled and the bus number is correct.")
except Exception as e:
print(f"An error occurred: {e}")