【问题标题】:Interrupt a pySerial readline in another thread在另一个线程中中断 pySerial readline
【发布时间】:2021-09-24 15:37:40
【问题描述】:

我正在使用 pySerial 通过 USB 与微控制器通信,大部分通信由桌面 python 脚本发起,该脚本发送命令包并等待回复。

但也有可能由微控制器发送的警报数据包,​​无需来自 python 脚本的命令。在这种情况下,我需要监视读取流中的任何警报。

为了处理警报,我专门使用一个单独的进程来调用readline() 并循环它,如下所示:

    def serialMonitor(self):

        while not self.stopMonitor:
            self.lock.acquire()
            message = self.stream.readline()
            self.lock.release()
            self.callback(message)
  

在一个类中。然后该函数在一个单独的过程中由

启动
self.monitor = multiprocessing.Process(target = SerialManager.serialMonitor, args = [self])

每当发送命令包时,命令函数需要收回对流的控制,为此它必须中断处于阻塞状态的readline() 调用。如何中断readline() 通话?有什么方法可以安全地终止进程吗?

【问题讨论】:

    标签: python python-multiprocessing pyserial


    【解决方案1】:

    您可以使用.terminate() 终止多处理进程。这安全吗?对于 readline 案例来说可能没问题。

    但是,这不是我在这里处理事情的方式。当我阅读您的场景时,有两种可能性:

    • MCU 启动警报包
    • 计算机向 MCU 发送数据(MCU 可能会做出响应)

    我假设 MCU 在计算机发起交换时不会发送警报包。

    所以我会以一个小的超时时间启动串行对象,并在我不使用它时将它留在一个循环中。我的整体流程是这样的:

    ser = Serial(PORT, timeout=1)
    response = None
    command_to_send = None
    running = True
    while running: # event loop
        while running and not command_to_send and not line:
            try:
                line = ser.readline()
            except SerialTimeoutException:
                pass
    
        if not command_to_send:
            process_mcu_alert(line)
    
        else:
            send_command(command_to_send)
            command_to_send = None
            response = ser.readline()
    

    这只是一个草图,因为它需要在线程或子进程中运行,因为readline() 确实是阻塞的,所以你需要一些线程安全的方法来设置command_to_sendrunning(用于优雅地退出)并获得response,您可能希望将所有这些状态包装在一个类中。它的精确实现取决于你在做什么,但原理是一样的——有 one 循环来处理串行端口的读写,让它超时以相对快速地响应(你如果需要,可以设置较小的超时时间),并让它公开一些您可以处理的接口。

    遗憾的是,据我所知,python 没有兼容 asyncio 的串行库,否则这种方法看起来会更整洁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多