如何解决subprocess.stdout.readline()无数据时的阻塞问题?
解决subprocess.stdout.readline()阻塞超时问题
原代码的核心问题是proc.stdout.readline()会永久阻塞,导致循环的总超时判断完全失效——只要readline卡住,程序就不会回到循环条件检查步骤。
方案一:用select模块实现带超时的逐行读取
通过select.select()监听标准输出的可读状态,每次等待数据时设置一个短超时,既能实时读取输出,又能定期检查总超时是否到达:
import subprocess import time import select cmd = ["node", "transformerMonitor.js", "-h", "sample.com", "-s", "123"] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) total_timeout = 120 start_time = time.time() poll_interval = 1 # 单次等待数据的超时时间(秒) while time.time() - start_time < total_timeout: # 检查stdout是否有可读数据,超时时间为poll_interval ready, _, _ = select.select([proc.stdout], [], [], poll_interval) if ready: out = proc.stdout.readline() if not out: # 读取到空内容,说明子进程已终止 break print(out.strip()) # 超时后自动回到循环,判断总超时是否触发 # 清理子进程,避免僵尸进程 proc.terminate() proc.wait()
方案二:用communicate()实现整体超时(适合非实时逐行场景)
如果不需要实时逐行处理输出,可以直接用communicate(timeout)设置整体超时,超时后终止子进程:
import subprocess cmd = ["node", "transformerMonitor.js", "-h", "sample.com", "-s", "123"] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) total_timeout = 120 try: stdout, stderr = proc.communicate(timeout=total_timeout) for line in stdout.splitlines(): print(line) except subprocess.TimeoutExpired: proc.terminate() proc.wait() print("设备无响应,已超时退出")
内容的提问来源于stack exchange,提问作者saikumar gaddam
相关产品推荐
相关产品推荐

