【问题标题】:How can I trap CAN bus exceptions such as 'Network down' from within python-can interfaces?如何从 python-can 接口中捕获 CAN 总线异常,例如“网络故障”?
【发布时间】:2017-03-31 11:51:08
【问题描述】:

我有一个小型 python 项目来模拟我构建的支持 CAN 的电子设备。该项目有一个 shell 解释器来与模拟的电子设备进行交互。我现在想捕获从 python-can 运行实例中抛出的异常,并在主 shell UI 中打印友好的错误消息,而不是让完整的堆栈跟踪显示混乱。

例如,如果我在未配置 can0 接口的情况下运行我的脚本(即在执行 ip link set can0 up type can bitrate 250000 之前),我会得到如下堆栈跟踪:

Failed to send: Timestamp:        0.000000        ID: 0541    000    DLC: 8    01 1a c4 13 00 00 e2 04
> Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.6/site-packages/can/notifier.py", line 39, in rx_thread
    msg = self.bus.recv(self.timeout)
  File "/usr/lib/python3.6/site-packages/can/interfaces/socketcan_native.py", line 341, in recv
    packet = capturePacket(self.socket)
  File "/usr/lib/python3.6/site-packages/can/interfaces/socketcan_native.py", line 274, in capturePacket
    cf, addr = sock.recvfrom(can_frame_size)
OSError: [Errno 100] Network is down

请注意,上面的“>”符号是我的迷你 shell 提示符。这看起来很丑,对吧。

我首先尝试派生SocketcanNative_Bus 并覆盖recv() 方法,但随后我的新类被拒绝,因为/usr/lib/python3.6/site-packages/can/interfaces/interface.py 中有一个检查,它根据知名模块列表验证接口类名称。所以这可能不是完全可行的方法。

在我尝试其他愚蠢的事情之前,python-can 是否提供了一些方法来拦截在数据包传输期间或 CAN 接口出现故障时在Notifier 线程中发生的操作系统错误?

请注意,由于我使用的是 USB CAN 适配器,因此仅在脚本启动时检查网络状态是没有意义的,因为在脚本运行时也可以拔下 CAN 适配器。所以唯一相关的方法是捕获python-can模块抛出的异常,并在主线程中显示友好的消息。

【问题讨论】:

    标签: python exception-handling can-bus


    【解决方案1】:

    我仍然不知道这是否是 python-can 开发人员的意图,但这是我最近的工作尝试。我正在重写 SocketcanNative_Bus 类实例的 recv() 方法,也就是 bus

    can.rc['interface'] = 'socketcan_native'
    can.rc['channel'] = args[1]
    
    from can.interfaces.socketcan_native import SocketcanNative_Bus
    def recv(self, timeout=None):
        try:
            return SocketcanNative_Bus.recv(self, timeout)
        except OSError as e:
            print(str(e))
            return None
    
    try:
        import types
        bus = can.interface.Bus()
        bus.recv = types.MethodType(recv, bus)
    
    except OSError as e:
        print('Error {0}: {1}'.format(e.errno, e.strerror), file=sys.stderr)
    

    我使用 Python 的 types.MethodType() 动态覆盖了 bus 实例的方法 recv()。它被称为patching,解释为elsewhere on Stackoverflow

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 2020-10-07
      • 1970-01-01
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多