Skip to content

python-can

python-can provides a consistent Python API for sending, receiving, filtering and logging CAN and CAN FD frames on Windows and Linux.

Supported Interfaces

Common backends include:

  • socketcan for Linux SocketCAN interfaces such as can0
  • pcan for PCAN devices and compatible CANmeleon applications on Windows
  • Other vendor backends listed in the python-can interface documentation

Prepare the Environment

Linux SocketCAN

bash
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
ip -details link show can0

For CAN FD:

bash
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 1000000 dbitrate 5000000 fd on
sudo ip link set can0 up

Windows

Install the device driver or the required CANmeleon protocol application before opening the adapter from Python.

Install python-can

bash
python -m pip install python-can

Quick Start

python
import can

# Windows PCAN-compatible interface
bus = can.Bus(interface="pcan", channel="PCAN_USBBUS1", bitrate=500000)

# For Linux, use:
# bus = can.Bus(interface="socketcan", channel="can0")

message = can.Message(
    arbitration_id=0x123,
    data=[0x11, 0x22, 0x33, 0x44],
    is_extended_id=False,
)

bus.send(message)
received = bus.recv(timeout=2.0)
print(received)
bus.shutdown()

Create a Bus Object

python
import can

def open_socketcan(channel="can0"):
    return can.Bus(interface="socketcan", channel=channel)

def open_pcan(channel="PCAN_USBBUS1", bitrate=500000):
    return can.Bus(
        interface="pcan",
        channel=channel,
        bitrate=bitrate,
    )

The exact arguments depend on the selected backend. SocketCAN timing is normally configured with the Linux ip command before Python opens the interface.

CAN Messages

python
import can

# Standard 11-bit ID
standard = can.Message(
    arbitration_id=0x123,
    data=[1, 2, 3, 4],
    is_extended_id=False,
)

# Extended 29-bit ID
extended = can.Message(
    arbitration_id=0x18FF50E5,
    data=[0x10, 0x20],
    is_extended_id=True,
)

# Remote frame
remote = can.Message(
    arbitration_id=0x321,
    is_remote_frame=True,
    dlc=8,
    is_extended_id=False,
)

Send CAN and CAN FD Frames

python
def send_classical(bus):
    msg = can.Message(
        arbitration_id=0x123,
        data=[0x11, 0x22, 0x33, 0x44],
        is_extended_id=False,
    )
    bus.send(msg, timeout=1.0)


def send_can_fd(bus):
    msg = can.Message(
        arbitration_id=0x456,
        data=bytes(range(32)),
        is_fd=True,
        bitrate_switch=True,
        is_extended_id=False,
    )
    bus.send(msg, timeout=1.0)

The interface must be opened in CAN FD mode before sending FD frames. On SocketCAN, configure fd on; vendor backends may require an fd=True option or a timing string.

Periodic Transmission

python
import time
import can

msg = can.Message(
    arbitration_id=0x100,
    data=[0, 1, 2, 3, 4, 5, 6, 7],
    is_extended_id=False,
)

task = bus.send_periodic(msg, period=0.1)
time.sleep(5)
task.stop()

Receive Frames

Blocking Receive

python
while True:
    msg = bus.recv(timeout=1.0)
    if msg is not None:
        print(f"{msg.timestamp:.6f} {msg.channel} {msg.arbitration_id:X} {msg.data.hex()}")

Asynchronous Notification

python
import can

class Printer(can.Listener):
    def on_message_received(self, msg):
        print(msg)

listener = Printer()
notifier = can.Notifier(bus, [listener])

# Stop before closing the application:
# notifier.stop()
# bus.shutdown()

Filters

python
filters = [
    {"can_id": 0x123, "can_mask": 0x7FF, "extended": False},
    {"can_id": 0x456, "can_mask": 0x7FF, "extended": False},
]
bus.set_filters(filters)

Filters reduce unwanted traffic. Whether filtering is performed in hardware, the driver or Python depends on the backend.

Logging and Playback

python
import can

logger = can.Logger("capture.asc")
notifier = can.Notifier(bus, [logger])

# ... collect frames ...

notifier.stop()
logger.stop()

python-can supports several log formats. Select the filename extension appropriate for the intended reader or playback workflow.

Troubleshooting

  • Interface not found: verify the driver and channel name. On Linux, run ip link show.
  • Permission denied: run with appropriate CAN-device permissions; avoid using elevated privileges as a permanent application design.
  • No received frames: check CAN_H / CAN_L, ground, bit rate, sample point and termination.
  • Bus-Off: stop transmission, correct the physical or timing problem, then reset the interface.
  • CAN FD send fails: confirm that both the interface and target network use CAN FD and matching ISO / Non-ISO and data-phase timing.

Enable library diagnostics when needed:

python
import logging
logging.basicConfig(level=logging.DEBUG)

References

Driving Intelligent Connections, Empowering the Future