使用subprocess.run捕获Python输出并邮件发送时遇阻塞与循环警告
问题分析与解决
1. 原subprocess.run阻塞的原因
使用capture_output=True时,会同时捕获子进程的stdout和stderr到管道中。如果子进程输出大量内容(比如你遇到的重复FutureWarning),管道缓冲区会被占满,子进程会等待父进程读取管道数据,但subprocess.run()默认是等待子进程完全结束后才会读取管道,这就导致了死锁阻塞。
2. 修改后重复警告的问题
改成stdout=subprocess.PIPE后,stderr默认继承父进程的标准错误输出,子进程里的FutureWarning会持续输出到stderr;如果你的log_mod.setup_logging配置了将stderr也写入日志,就会导致警告信息重复出现在终端和日志里,还夹杂正常输出。
解决步骤
步骤1:修复subprocess阻塞问题,正确处理输出
不要只捕获stdout,要同时处理stderr避免缓冲区溢出。推荐将stderr合并到stdout统一捕获,既不会阻塞,又能整合所有输出:
completed_process = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # 将stderr合并到stdout一起捕获 text=True # 以文本模式读取,避免字节串处理 ) captured_output = completed_process.stdout
步骤2:消除根源的FutureWarning
警告来自local_loadscript.py第312行的代码:
bdf.columns = bdf.columns.str.strip().str.replace('.', '').str.replace(' ', '').str.lower()
这里str.replace('.', '')默认regex=True,.在正则中是通配符而非字面点号,因此触发警告。只需显式指定regex=False即可解决:
# 把.当作字面字符替换,消除警告 bdf.columns = bdf.columns.str.strip().str.replace('.', '', regex=False).str.replace(' ', '', regex=False).str.lower()
消除警告后,子进程就不会持续输出重复信息,日志和终端输出恢复正常。
步骤3:优化日志记录逻辑
确保log_mod.log()不会重复记录输出。如果已经通过subprocess捕获了完整输出,直接将捕获的内容写入日志即可,避免日志系统重复捕获子进程的stderr输出。
内容的提问来源于stack exchange,提问作者DarrenC
相关产品推荐
相关产品推荐

