python-can包的核心子包 / 模块结构 和常用函数 / 类(方法),我会按照 "模块分类 + 核心功能 + 常用接口" 的逻辑拆解,结合实际使用场景说明,让你清晰掌握这个包的核心组成和用法。
一、python-can 整体包结构(核心子包 / 模块)
python-can 是面向对象设计的库,核心功能集中在多个子模块(子包)中,而非纯函数式调用。以下是最常用的子模块及作用:
| 子模块 / 子包 | 核心作用 |
|---|---|
(1)can.interface |
总线接口入口(创建不同硬件 / 虚拟总线实例,最核心模块) |
(2)can.Message |
CAN 消息类(构造 / 解析 CAN 帧,所有收发操作的核心数据载体) |
(3)can.Notifier |
消息通知器(异步接收消息,绑定监听器实现回调) |
(4)can.Listener |
监听器基类(定义消息处理逻辑,含内置实现如Printer/Logger) |
(5)can.filters |
消息过滤工具(筛选指定 ID 的 CAN 消息) |
(6)can.BusABC |
总线抽象基类(所有总线的父类,定义通用总线方法) |
(7)can.logger / can.player |
日志工具(记录 CAN 消息到文件 / 从文件回放消息) |
(8)can.errors |
异常类(定义 CAN 通信相关的异常,如CanError) |
(9)can.util |
通用工具函数(如字节转换、ID 格式处理) |
以上是9个子模块,其中包含了硬件设置,消息发送与接收,报文信号的录制,错误处理等各种不同子模块。
二、核心子模块 + 常用函数 / 类(方法)详解
以下是每个核心模块的常用接口(类、方法、函数),附带使用示例和参数说明。
1. 核心入口:can.interface 模块
作用:创建不同类型的 CAN 总线实例(虚拟 / 硬件),是所有操作的起点(也就是识别硬件,创建硬件接口,设置波特率等基础参数的过程)。
常用函数:can.interface.Bus() #需要分清的是interface是class,bus则是函数(准确来说是被class包含的函数)
-
功能:根据配置创建总线实例(自动适配接口类型)。
-
参数 (核心):一共五个核心参数
(1)interface:总线接口类型(如"virtual"/"socketcan"/"pcan"/"kvaser");(2)channel:总线通道(如"virtual_channel"/"can0"/"PCAN_USBBUS1");(3)bitrate:CAN 总线波特率(如 500000、250000);(4)fd:是否启用 CAN FD(默认 False,支持则需要设置为True)(即python-can的interface子模块中也是支持CAN-FD的);(5)filters:消息过滤器(可选,初始化时设置过滤规则)。
-
示例 :
python
pythonimport can # 创建虚拟总线 bus = can.interface.Bus( interface="virtual", channel="vcan0", bitrate=500000, #注意这里的单位是bit filters=[{"can_id": 0x123, "can_mask": 0xFFF, "extended": False}]#这里的是采取的是列表推导式,内部采取的是字典格式 ) # 创建Linux SocketCAN总线 # bus = can.interface.Bus(interface="socketcan", channel="can0", bitrate=500000)
2. 数据载体:can.Message 类
作用:构造 / 解析 CAN 消息帧,是收发的核心数据结构。
常用初始化参数(构造消息):
| 参数 | 含义 |
|---|---|
arbitration_id |
CAN 帧仲裁 ID(int,11 位标准帧:0~0x7FF;29 位扩展帧:0~0x1FFFFFFF) |
data |
消息数据(bytes/bytearray,最多 8 字节;CAN FD 支持 64 字节) |
is_extended_id |
是否为扩展帧(bool,False=11 位,True=29 位,默认 False) |
is_remote_frame |
是否为远程帧(bool,仅请求数据,无 data,默认 False),即使设置了data,实际发送时也会被丢弃(远程帧本身不携带数据)。 |
is_error_frame |
是否为错误帧(bool,默认 False) |
timestamp |
时间戳(float,可选,接收时自动填充) |
注意表格中的几个默认参数,这几个参数都是默认的,可以不写的。不写就采取默认值
常用属性 / 方法:
msg.arbitration_id:获取 / 修改仲裁 ID;msg.data:获取 / 修改消息数据;msg.is_extended_id:判断是否为扩展帧;msg.__repr__():返回消息的可读字符串(便于打印)。
示例:
python
python
# 构造11位标准帧
msg1 = can.Message(
arbitration_id=0x123,
data=[10,20,30,40,50,60,70,80], # 字节数据,长度≤8
is_extended_id=False
)
# 构造29位扩展帧
msg2 = can.Message(
arbitration_id=0x12345678,
data=bytearray([0x01, 0x02, 0x03]), # 字节数组格式
is_extended_id=True
)
# 打印消息信息
print(msg1) # 输出:Message(arbitration_id=0x123, data=b'hello', is_extended_id=False)
这里需要知道message不是一个函数,而是一个类,而msg1 = can.Message(),则是实例化,msg1就是实例化的对象。这里不能认为是函数的调用,而是类的实例化
3. 总线操作:BusABC 基类的常用方法
can.interface.Bus() 创建的实例继承自BusABC,以下是实例的核心方法(即 "常用函数"):
| 方法 | 功能 |
|---|---|
bus.send(msg, timeout=None) |
发送 CAN 消息- msg:can.Message实例- timeout:超时时间(秒,None = 无限等待)- 异常:can.CanError(发送失败) |
bus.recv(timeout=None) |
接收 CAN 消息- timeout:超时时间(秒,None = 无限等待,0 = 非阻塞)- 返回:can.Message实例(成功)/None(超时) |
bus.set_filters(filters) |
设置消息过滤器- filters:过滤规则列表(见下文)- None:关闭过滤 |
bus.shutdown() |
关闭总线(释放硬件资源,程序结束前建议调用) |
bus.flush_tx_buffer() |
清空发送缓冲区 |
bus.flush_rx_buffer() |
清空接收缓冲区 |
示例(收发消息):
python
运行
import can
bus = can.interface.Bus(interface="virtual", channel="vcan0", bitrate=500000)
# 发送消息
msg = can.Message(arbitration_id=0x123, data=b"test")
try:
bus.send(msg, timeout=1.0)
print("消息发送成功")
except can.CanError:
print("消息发送失败")
# 接收消息
recv_msg = bus.recv(timeout=2.0)
if recv_msg:
print(f"接收消息:ID=0x{recv_msg.arbitration_id:X}, 数据={recv_msg.data}")
# 关闭总线
bus.shutdown()
4. 消息过滤:can.filters 模块
作用:筛选只接收指定 ID 的 CAN 消息,减少无关数据干扰。
过滤规则格式:
python
运行
# 单条规则:{"can_id": 目标ID, "can_mask": 掩码, "extended": 是否扩展帧}
# 掩码规则:ID & mask == can_id & mask 时匹配
filters = [
{"can_id": 0x123, "can_mask": 0xFFF, "extended": False}, # 匹配11位ID=0x123的消息
{"can_id": 0x456000, "can_mask": 0xFFFF00, "extended": True} # 匹配29位ID前16位为0x456的消息
]
常用用法:
python
运行
bus.set_filters(filters) # 设置过滤规则
bus.set_filters(None) # 关闭过滤(接收所有消息)
5. 异步接收:can.Notifier + can.Listener
作用:异步监听 CAN 消息(无需主动循环recv()),收到消息自动触发处理逻辑。
(1)can.Notifier 类
- 初始化:
notifier = can.Notifier(bus, listeners, timeout=1.0)bus:总线实例;listeners:监听器列表(可多个,按顺序执行);timeout:监听超时时间。
- 常用方法:
notifier.stop():停止监听;notifier.add_listener(listener):添加监听器;notifier.remove_listener(listener):移除监听器。
(2)can.Listener 基类(自定义监听器)
需继承Listener并实现on_message_received(msg)方法;也可使用内置监听器:
can.Printer():打印收到的消息(调试用);can.Logger(file_path):将消息记录到文件(.asc/.blf 格式);can.FileReader(file_path):从日志文件读取消息(回放用)。
示例(异步监听):
python
python
import can
import threading
# 自定义监听器
class MyListener(can.Listener):
def on_message_received(self, msg):
# 收到消息时执行的逻辑
print(f"自定义监听器:ID=0x{msg.arbitration_id:X}, 数据={msg.data}")
bus = can.interface.Bus(interface="virtual", channel="vcan0", bitrate=500000)
# 初始化监听器列表(内置Printer + 自定义MyListener)
listeners = [can.Printer(), MyListener()]
notifier = can.Notifier(bus, listeners)
# 发送测试消息(触发监听器)
bus.send(can.Message(arbitration_id=0x123, data=b"async test"))
# 保持程序运行(避免主线程退出)
threading.Event().wait()
# 停止监听(程序结束前执行)
notifier.stop()
bus.shutdown()
6. 工具类:can.logger / can.player
作用:记录 CAN 消息到文件(日志)、从日志文件回放消息(调试 / 复现场景)。
(1)记录消息到文件
python
运行
import can
bus = can.interface.Bus(interface="virtual", channel="vcan0", bitrate=500000)
# 创建日志器(保存到can_log.asc文件)
logger = can.Logger("can_log.asc")
notifier = can.Notifier(bus, [logger])
# 运行一段时间,记录收到的所有消息
input("按回车停止记录...")
notifier.stop()
bus.shutdown()
(2)从文件回放消息
python
运行
import can
bus = can.interface.Bus(interface="virtual", channel="vcan0", bitrate=500000)
# 读取日志文件
reader = can.FileReader("can_log.asc")
# 回放消息(按时间戳发送)
for msg in reader:
try:
bus.send(msg)
print(f"回放消息:{msg}")
except can.CanError:
print("回放失败")
bus.shutdown()
7. 通用工具:can.util 模块
包含少量辅助函数,常用的有:
can.util.hex2bytes(hex_str):将十六进制字符串转为字节(如hex2bytes("010203")→b'\x01\x02\x03');can.util.bytes2hex(byte_data):将字节转为十六进制字符串;can.util.compute_dlc(data):计算 CAN 消息的数据长度码(DLC)。
示例:
python
运行
import can.util
# 十六进制字符串转字节
hex_str = "12345678"
byte_data = can.util.hex2bytes(hex_str)
print(byte_data) # 输出:b'\x124Vx'
# 字节转十六进制字符串
hex_str2 = can.util.bytes2hex(byte_data)
print(hex_str2) # 输出:'12 34 56 78'
三、总结(核心关键点)
- 核心流程 :
can.interface.Bus()创建总线 →can.Message()构造消息 →bus.send()/bus.recv()收发 →bus.shutdown()释放资源; - 异步处理 :
Notifier + Listener实现无阻塞监听,自定义on_message_received处理消息; - 过滤机制 :
bus.set_filters()筛选指定 ID 消息,减少无效数据; - 工具辅助 :
Logger/FileReader实现消息记录 / 回放,util处理字节 / ID 格式转换。
这些是python-can最常用的子模块和接口,覆盖了 90% 以上的 CAN 通信场景(测试、硬件交互、数据解析、日志调试)。如果需要针对特定硬件(如 PCAN、USB-CAN)的接口配置,可补充说明,我会针对性讲解。