python在汽车电子行业中应用2—具体包的介绍和使用

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

    python 复制代码
    import 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 消息- msgcan.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'

三、总结(核心关键点)

  1. 核心流程can.interface.Bus() 创建总线 → can.Message() 构造消息 → bus.send()/bus.recv() 收发 → bus.shutdown() 释放资源;
  2. 异步处理Notifier + Listener 实现无阻塞监听,自定义on_message_received处理消息;
  3. 过滤机制bus.set_filters() 筛选指定 ID 消息,减少无效数据;
  4. 工具辅助Logger/FileReader 实现消息记录 / 回放,util 处理字节 / ID 格式转换。

这些是python-can最常用的子模块和接口,覆盖了 90% 以上的 CAN 通信场景(测试、硬件交互、数据解析、日志调试)。如果需要针对特定硬件(如 PCAN、USB-CAN)的接口配置,可补充说明,我会针对性讲解。

相关推荐
Dxy12393102168 小时前
Python的zip用法详解
开发语言·python
不知疲倦的仄仄8 小时前
第四天:Netty 核心原理深度解析&EventLoop、Future/Promise 与 Pipeline
linux·服务器·网络
橘颂TA8 小时前
【Linux 网络编程】网络是怎么 “跑” 起来的?从协议入门到 TCP/ IP 模型的底层逻辑
linux·运维·服务器·网络
我的golang之路果然有问题8 小时前
python中 unicorn 热重启问题和 debug 的 json
java·服务器·前端·python·json
lagrahhn8 小时前
scoop的使用
大数据·python·搜索引擎
智算菩萨8 小时前
【Python自然语言处理】实战项目:词向量表示完整实现指南
开发语言·python·自然语言处理
MOON404☾8 小时前
004.漏洞分析与利用
前端·网络·网络安全·系统安全·firefox
Elaine3368 小时前
【验证码识别算法性能对比实验系统——KNN、SVM、CNN 与多模态大模型的性能博弈与机理分析】
python·opencv·支持向量机·cnn·多模态·数字图像处理
SCBAiotAigc8 小时前
langchain1.x学习笔记(三):langchain之init_chat_model的新用法
人工智能·python·langchain·langgraph·deepagents