Python多进程(multiprocessing)下Telnet控制DDS遇BrokenPipeError求助
我正在编写带GUI的脚本以控制DDS设备,该设备通过Telnet实现控制。由于时序问题,我将Telnet控制逻辑放在子进程中运行。脚本可成功连接设备,但在尝试设置频率输出时出现Errno 32 BrokenPipeError。我通过终端Telnet以及仅运行主进程中的连接代码进行测试,均能正常运行无报错,仅在带GUI的完整脚本中使用子进程进行Telnet连接时出现该问题。
报错信息如下:
DDS connected! Process Process-1: Traceback (most recent call last): File "/usr/local/Cellar/python@3.9/3.9.16/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap self.run() File "/usr/local/Cellar/python@3.9/3.9.16/Frameworks/Python.framework/Versions/3.9/lib/python3.9/multiprocessing/process.py", line 108, in run self._target(*self._args, **self._kwargs) File "/Users/jakubdobosz/Library/CloudStorage/GoogleDrive-j.dobosz2@student.uw.edu.pl/Mój dysk/github/FrequencyDriftStabilizer/gui.py", line 46, in _handleStab handler.filterUpdate() File "/Users/jakubdobosz/Library/CloudStorage/GoogleDrive-j.dobosz2@student.uw.edu.pl/Mój dysk/github/FrequencyDriftStabilizer/src/handlerStabilization.py", line 155, in filterUpdate self._DDS.setFreq(self._DDSfreq) File "/Users/jakubdobosz/Library/CloudStorage/GoogleDrive-j.dobosz2@student.uw.edu.pl/Mój dysk/github/FrequencyDriftStabilizer/src/DDS_AD9912.py", line 91, in setFreq self._DDS.write(cmd.encode('UTF-8')) File "/usr/local/Cellar/python@3.9/3.9.16/Frameworks/Python.framework/Versions/3.9/lib/python3.9/telnetlib.py", line 292, in write self.sock.sendall(buffer) BrokenPipeError: [Errno 32] Broken pipe
请问能否在子进程中通过Telnet与设备通信?或是存在其他未排查到的问题?
完全可以在子进程中通过Telnet与设备通信,报错是由其他潜在问题导致的,以下是重点排查方向:
进程间资源共享问题:
不要在主进程中创建Telnet连接后传递给子进程。多进程环境下,父进程的socket文件描述符在子进程中复制后,若父进程意外关闭该资源,会导致子进程的连接直接断开。必须确保Telnet连接的创建、维护和关闭全在子进程内部完成,与主进程资源完全隔离。GUI主线程的资源干扰:
检查GUI框架(如Tkinter、PyQt)的主线程是否存在不当操作,比如意外回收了与Telnet相关的资源,或者事件循环的阻塞间接中断了子进程的连接。确保子进程拥有独立的生命周期,不受GUI主线程的资源清理操作影响。子进程生命周期管理:
排查子进程是否被意外终止或挂起。可以在子进程中添加详细日志,记录连接状态、命令发送时机等信息,确认执行setFreq前连接是否已经断开;同时检查是否存在GUI操作触发子进程退出但未处理重连的情况。时序与同步问题:
即便将逻辑移到子进程,仍可能存在时序问题:比如连接建立后未等待设备就绪就发送命令,或者多个子进程同时操作同一个Telnet连接。需确保子进程中连接完全建立后再执行命令,且同一时间只有一个进程与设备通信。子进程内连接有效性验证:
在子进程创建连接后,先发送简单的测试命令(如查询设备状态)验证连接有效性,再执行设置频率的操作,以此排除连接建立不彻底的问题。
内容的提问来源于stack exchange,提问作者Einaudi

