You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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')    
验证步骤
  1. 运行修改后的代码,检查是否还出现is_extended_id报错
  2. 如果仍有问题,就使用固定版本的方法安装python-can 3.3.4,同时改回原代码的socketcan_native后端

内容的提问来源于stack exchange,提问作者Hector Aguilar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 02:25:42