在另一个线程中中断 pySerial readline
Interrupt a pySerial readline in another thread
我正在使用 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)
里面一个class。然后通过
在单独的进程中启动该功能
self.monitor = multiprocessing.Process(target = SerialManager.serialMonitor, args = [self])
无论何时发送命令包,命令函数都需要收回对流的控制,为此它必须中断处于阻塞状态的 readline()
调用。如何中断 readline()
呼叫?有什么方法可以安全地终止进程吗?
您可以使用 .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_send
和 running
(用于正常退出)并获得 response
,您可能希望将所有这些状态包装在 class 中。具体实现取决于你在做什么,但原理是一样的---有一个循环处理串口的读写,让它超时响应快速(如果需要,您可以设置更小的超时),并让它公开一些您可以处理的接口。
很遗憾,据我所知,python 没有与 asyncio 兼容的串行库,否则这种方法看起来会更整洁。
我正在使用 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)
里面一个class。然后通过
在单独的进程中启动该功能self.monitor = multiprocessing.Process(target = SerialManager.serialMonitor, args = [self])
无论何时发送命令包,命令函数都需要收回对流的控制,为此它必须中断处于阻塞状态的 readline()
调用。如何中断 readline()
呼叫?有什么方法可以安全地终止进程吗?
您可以使用 .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_send
和 running
(用于正常退出)并获得 response
,您可能希望将所有这些状态包装在 class 中。具体实现取决于你在做什么,但原理是一样的---有一个循环处理串口的读写,让它超时响应快速(如果需要,您可以设置更小的超时),并让它公开一些您可以处理的接口。
很遗憾,据我所知,python 没有与 asyncio 兼容的串行库,否则这种方法看起来会更整洁。