初始化Serial对象导致multiprocessing模块异常问题排查
关于Multiprocessing结合串口读取无输出的问题分析与解决
我之前做工业数据采集项目时,刚好碰到过一模一样的坑!结合你的排查过程,问题大概率出在串口对象的进程兼容性上,下面给你拆解原因和对应的解决办法:
核心原因分析
- 串口对象无法被安全序列化:pyserial的
Serial内部封装了操作系统的硬件资源句柄(比如串口的文件描述符),而multiprocessing在创建子进程时(尤其是Windows的spawn模式),需要把父进程的对象序列化后传递给子进程。这类底层资源句柄根本没法被序列化,强行传递会导致子进程里的串口对象直接失效,甚至静默阻塞进程执行。 - 串口资源被独占:如果父进程先初始化了
Serial,子进程再尝试访问同一个串口时,会因为串口被父进程独占而卡住,或者抛出异常但没被捕获,导致进程没有任何输出。
可行的解决办法
1. 在子进程内部单独初始化串口
不要在父进程创建串口对象再传给子进程,让每个需要读取串口的子进程自己打开、管理串口连接。示例代码:
import multiprocessing from serial import Serial def serial_reader(): # 子进程内独立初始化串口 try: ser = Serial('COM3', 9600, timeout=1) while True: data = ser.readline() if data: print(f"Received: {data.decode().strip()}") except Exception as e: print(f"Serial reader error: {str(e)}") if __name__ == '__main__': # 必须用if __name__包裹主逻辑,避免Windows spawn模式下重复初始化 proc = multiprocessing.Process(target=serial_reader) proc.start() proc.join()
2. 用IPC隔离串口读取与数据处理
如果需要多个进程协作处理串口数据,建议让一个专门的子进程负责读取串口,然后通过Queue或Pipe把数据传递给其他进程。这样既避免了多进程直接操作串口的冲突,也解决了对象序列化的问题:
import multiprocessing from serial import Serial def serial_reader(data_queue): ser = Serial('COM3', 9600, timeout=1) while True: data = ser.readline() if data: data_queue.put(data.decode().strip()) def data_processor(data_queue): while True: raw_data = data_queue.get() # 这里可以添加数据处理逻辑 print(f"Processed data: {raw_data}") if __name__ == '__main__': queue = multiprocessing.Queue() reader_proc = multiprocessing.Process(target=serial_reader, args=(queue,)) processor_proc = multiprocessing.Process(target=data_processor, args=(queue,)) reader_proc.start() processor_proc.start() reader_proc.join() processor_proc.join()
3. 检查进程启动模式与异常捕获
- Windows系统默认用
spawn模式,必须确保主程序逻辑在if __name__ == '__main__':块内,否则会重复执行模块代码导致异常。 - 一定要在子进程代码里添加异常捕获,很多时候无输出是因为抛出了异常但没被打印,比如串口端口号错误、波特率不匹配等。
内容的提问来源于stack exchange,提问作者ArkanSaaS
相关产品推荐
相关产品推荐

