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 firmware 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 firmware 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
蜀ICP备2023000218号-2