Python CAN Bus Interface
The python-can library provides Controller Area Network (CAN) support for Python developers, offering common abstractions to various hardware devices and a suite of utilities for sending and receiving messages on a CAN bus. It supports CPython and PyPy, running on Mac, Linux, and Windows. The current version is 4.6.1, with frequent updates to the 4.x series.
Warnings
- breaking The `socketcan_ctypes` and `socketcan_native` implementations were removed in version 4.0.0 after a deprecation period.
- gotcha Failing to properly shut down the CAN bus can lead to resource leaks or unexpected behavior, especially in long-running applications.
- gotcha Hardware-specific drivers and system-level configuration are often required for `python-can` to function with physical CAN interfaces.
- gotcha Configuration of `python-can` can be done via code, environment variables, or a configuration file. Inconsistent or conflicting settings across these methods can lead to unexpected bus behavior.
Install
-
pip install python-can -
pip install 'python-can[vector]' # for Vector hardware pip install 'python-can[kvaser]' # for Kvaser hardware
Imports
- can
import can
- can.Bus
from can import Bus
- can.Message
from can import Message
Quickstart
import can
import os
# For a runnable example without physical hardware, you can set up a virtual CAN interface:
# On Linux, run in terminal: `sudo modprobe vcan && sudo ip link add dev vcan0 type vcan && sudo ip link set vcan0 up`
# Then, use channel='vcan0' below.
# Configure bus interface and channel (can be set via environment variables or config file too)
# Using 'socketcan' with 'vcan0' is a common virtual setup on Linux.
# Replace 'socketcan' and 'vcan0' with your actual interface and channel if using real hardware.
BUS_INTERFACE = os.environ.get('CAN_INTERFACE', 'socketcan')
CAN_CHANNEL = os.environ.get('CAN_CHANNEL', 'vcan0')
try:
# Using 'with' statement ensures the bus is properly shut down
with can.Bus(interface=BUS_INTERFACE, channel=CAN_CHANNEL, receive_own_messages=True) as bus:
# Create a CAN message
message = can.Message(
arbitration_id=0x123, # Standard or extended ID
is_extended_id=False, # Set to True for extended IDs
data=[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], # 0-8 bytes for CAN 2.0, up to 64 for CAN FD
is_fd=False, # Set to True for CAN FD messages
bitrate_switch=False, # Relevant for CAN FD
error_state_indicator=False # Relevant for CAN FD
)
print(f"Attempting to send message: {message}")
bus.send(message)
print(f"Message sent successfully on {bus.channel} using {bus.interface} interface.")
# Optional: Receive a message
# received_message = bus.recv(10.0) # Wait up to 10 seconds for a message
# if received_message:
# print(f"Received message: {received_message}")
# else:
# print("No message received.")
except can.CanError as e:
print(f"Error sending message: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")