Python CAN 4.1.0下socketcan_native与extended_id参数报错求助
为啥会报错?
init() got an unexpected keyword argument 'is_extended_id'这个错误的核心原因很明确:
- python-can 4.x版本已经彻底移除了
socketcan_native后端,换成了统一的socketcan后端 - 你用的旧代码还在调用已废弃的
socketcan_native,导致内部消息初始化时参数不匹配,触发报错
另外你提到apt-get update/upgrade会自动升级python-can的问题,下面也会给出解决办法。
怎么解决?
1. 修改代码中的CAN总线后端
把代码里初始化CAN总线的那一行,将socketcan_native替换为新版本支持的socketcan即可:
原代码:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
修改为:
bus = can.interface.Bus(channel='can0', bustype='socketcan')
2. 固定python-can版本(避免自动升级)
如果不想使用最新版python-can,或者改完后端仍有问题,可以固定安装兼容旧代码的版本:
- 先卸载当前版本:
pip uninstall python-can -y
- 安装支持
socketcan_native的3.3.4版本:
pip install python-can==3.3.4
- 阻止
apt自动升级python-can:
sudo apt-mark hold python3-can
这样再执行apt-get update/upgrade就不会自动升级python-can了。
修改后的完整代码
#!/usr/bin/python3 # ## obdii_logger.py # # This python3 program sends out OBDII request then logs the reply to the sd card. # For use with PiCAN boards on the Raspberry Pi # # 24-08-16 SK Pang # import RPi.GPIO as GPIO import can import time import os import queue from threading import Thread led = 22 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(led,GPIO.OUT) GPIO.output(led,True) # OBD-II PIDs定义 ENGINE_COOLANT_TEMP = 0x05 ENGINE_RPM = 0x0C VEHICLE_SPEED = 0x0D THROTTLE = 0x11 PID_REQUEST = 0x7DF PID_REPLY = 0x7E8 outfile = open('log.txt','w') print('\n\rCAN Rx test') print('Bring up CAN0....') # 启动can0接口,波特率500kbps os.system("sudo /sbin/ip link set can0 up type can bitrate 500000") time.sleep(0.1) print('Ready') try: # 替换为新版本支持的socketcan后端 bus = can.interface.Bus(channel='can0', bustype='socketcan') except OSError: print('Cannot find PiCAN board.') GPIO.output(led,False) exit() def can_rx_task(): # 接收线程 while True: message = bus.recv() if message.arbitration_id == PID_REPLY: q.put(message) # 把消息放入队列 def can_tx_task(): # 发送线程 while True: GPIO.output(led,True) # 发送冷却液温度请求 msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,ENGINE_COOLANT_TEMP,0x00,0x00,0x00,0x00,0x00],extended_id=False) bus.send(msg) time.sleep(0.05) # 发送发动机转速请求 msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,ENGINE_RPM,0x00,0x00,0x00,0x00,0x00],extended_id=False) bus.send(msg) time.sleep(0.05) # 发送车速请求 msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,VEHICLE_SPEED,0x00,0x00,0x00,0x00,0x00],extended_id=False) bus.send(msg) time.sleep(0.05) # 发送节气门位置请求 msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,THROTTLE,0x00,0x00,0x00,0x00,0x00],extended_id=False) bus.send(msg) time.sleep(0.05) GPIO.output(led,False) time.sleep(0.1) q = queue.Queue() rx = Thread(target = can_rx_task) rx.start() tx = Thread(target = can_tx_task) tx.start() temperature = 0 rpm = 0 speed = 0 throttle = 0 c = '' count = 0 # 主循环 try: while True: for i in range(4): while(q.empty() == True): # 等待消息 pass message = q.get() c = '{0:f},{1:d},'.format(message.timestamp,count) if message.arbitration_id == PID_REPLY and message.data[2] == ENGINE_COOLANT_TEMP: temperature = message.data[3] - 40 # 转换为摄氏度 if message.arbitration_id == PID_REPLY and message.data[2] == ENGINE_RPM: rpm = round(((message.data[3]*256) + message.data[4])/4) # 转换为转速 if message.arbitration_id == PID_REPLY and message.data[2] == VEHICLE_SPEED: speed = message.data[3] # 转换为公里/小时 if message.arbitration_id == PID_REPLY and message.data[2] == THROTTLE: throttle = round((message.data[3]*100)/255) # 转换为百分比 c += '{0:d},{1:d},{2:d},{3:d}'.format(temperature,rpm,speed,throttle) print('\r {} '.format(c)) print(c,file = outfile) # 保存数据到文件 count += 1 except KeyboardInterrupt: # 捕获键盘中断 GPIO.output(led,False) outfile.close() # 关闭日志文件 os.system("sudo /sbin/ip link set can0 down") print('\n\rKeyboard interrupt')
验证步骤
- 运行修改后的代码,检查是否还出现
is_extended_id报错 - 如果仍有问题,就使用固定版本的方法安装python-can 3.3.4,同时改回原代码的
socketcan_native后端
内容的提问来源于stack exchange,提问作者Hector Aguilar
相关产品推荐
相关产品推荐

