python-can is a powerful Python library for working with CAN (Controller Area Network) interfaces. It provides a convenient API for sending, receiving, logging, and interpreting CAN messages, and is widely used in vehicle diagnostics, research, and cybersecurity tasks.
This tutorial will walk you through installing, configuring, and using python-can on a Linux system with SocketCAN support.
By the end of this chapter, you will be able to:
- Install and configure
python-canon a Linux machine - Set up a virtual or physical CAN interface using SocketCAN
- Write and run Python scripts that send and receive CAN messages
- Understand best practices for logging and analyzing CAN traffic
- A Linux system (Ubuntu or Debian-based preferred)
python3andpipinstalled- CAN interface (USB-CAN adapter like PEAK, ValueCAN, or virtual
vcan)
Install the python-can package using pip:
pip install python-canTo verify installation:
python3 -c "import can; print(can.__version__)"To set the default interface to using the .canrc configuration file for python-can, you need to create or edit the .canrc file in your home directory. Here is a step-by-step guide:
Create a .canrc file in your home directory if it doesn't already exist, and configure it to use vcan0 as the default interface.
nano ~/.canrcAdd the following content to the .canrc file:
[default]
interface = socketcan
channel = vcan0
#channel = can0
bitrate = 500000This configuration sets socketcan as the interface type, vcan0 as the channel, and a bitrate of 500000. Change channel to your interface name like vcan0 or can0.
Here's how you can create a Python script that uses the vcan0 interface configured in .canrc:
import can
def setup_can_interface():
# Set up the CAN bus using the default interface set in .canrc
can_bus = can.interface.Bus()
return can_bus
def main():
# Set up the CAN interface
can_bus = setup_can_interface()
# Example: Send a CAN message
message = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], is_extended_id=False)
try:
can_bus.send(message)
print("Message sent on vcan0")
except can.CanError:
print("Message NOT sent")
# Example: Receive a CAN message
try:
received_message = can_bus.recv(timeout=1.0)
if received_message:
print(f"Message received: {received_message}")
else:
print("No message received within timeout period")
except can.CanError:
print("Error receiving message")
if __name__ == "__main__":
main()-
Setup CAN Interface:
- The
setup_can_interfacefunction initializes the CAN interface using the configuration specified in the.canrcfile.
- The
-
Main Function:
- It sets up the CAN interface by calling
setup_can_interface. - It sends a sample CAN message.
- It receives a CAN message with a timeout of 1 second.
- It sets up the CAN interface by calling
After setting up the vcan0 interface and configuring the .canrc file, you can run the Python script:
python your_script_name.pyMake sure to replace your_script_name.py with the actual name of your Python script file.
This example sets python-can to use vcan0 as the default CAN interface based on the .canrc configuration. You can change this to can0 or whatever other interface you wish to use.
Create and bring up a virtual CAN interface:
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0For a USB CAN adapter using SocketCAN:
sudo ip link set can0 up type can bitrate 500000
sudo ifconfig can0 upReplace can0 with the correct interface name (ip link show can help).
import can
bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
print("Listening for messages...")
for msg in bus:
print(msg)import can
bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
msg = can.Message(arbitration_id=0x123, data=[0x11, 0x22, 0x33], is_extended_id=False)
try:
bus.send(msg)
print("Message sent")
except can.CanError:
print("Message NOT sent")Use can.Logger to save messages:
import can
bus = can.interface.Bus(channel='vcan0', bustype='socketcan')
logger = can.Logger("logfile.log")
for i in range(10):
msg = bus.recv(timeout=1.0)
if msg:
logger(msg)
print(f"Logged: {msg}")- Use virtual CAN for testing before touching a real vehicle
- Log everything — CAN traffic is noisy and transient
- Introduce delays when sending many messages to avoid buffer overflows
- Always match bitrate with the vehicle network
| Issue | Solution |
|---|---|
OSError: No such device |
Interface not set up — check with ip link |
can.CanError on send |
Bus might be down or misconfigured |
| No messages received | Try candump any in another terminal |
- python-can documentation
can-utils(candump,cansend) for quick CLI tests- SocketCAN developer documentation
- Open DBC databases for message decoding