
本文详解如何利用 pexpect 库让两个独立的 python 脚本通过标准输入/输出进行可靠通信,重点解决因输出缓冲导致的阻塞与同步失败问题,并提供可立即运行的最小化示例。
本文详解如何利用 pexpect 库让两个独立的 python 脚本通过标准输入/输出进行可靠通信,重点解决因输出缓冲导致的阻塞与同步失败问题,并提供可立即运行的最小化示例。
在 Python 进程间通信(IPC)场景中,当受限于必须通过终端交互(如模拟用户输入、集成遗留 CLI 工具)时,pexpect 是一个强大且常用的选择。然而,初学者常遇到“脚本看似运行但无响应”或“消息未被接收/回显”的问题——这几乎总是由 标准输出缓冲(stdout buffering) 引起:print() 默认行缓冲(在 TTY 中)或全缓冲(在重定向/子进程中),导致提示符 > 或响应内容迟迟不刷新到管道,pexpect.spawn 便无法及时匹配并继续执行。
✅ 正确做法:显式控制输出刷新与同步标记
核心原则是:用明确、唯一的字符串作为通信锚点(sync tokens),并确保它们立即刷新到 stdout。避免依赖未刷新的 input(">") 提示——因为 input() 内部虽会打印 >,但该输出可能滞留在缓冲区中,pexpect 无法捕获。
✅ 修改后的可靠示例
script_2.py(被控脚本,需主动刷新)
# script_2.py
print("READY") # 同步标记1:表示已启动并准备就绪
print(end="", flush=True) # 确保立即刷新(关键!)
try:
user_input = input(">")
print(f"Echo: {user_input}") # 处理并响应
print("DONE") # 同步标记2:表示响应已完成
print(end="", flush=True) # 再次强制刷新
except EOFError:
pass
script_1.py(主控脚本,使用 pexpect 驱动)
# script_1.py
import pexpect
import sys
# 启动子进程(注意路径需替换为实际路径)
child = pexpect.spawn(f"{sys.executable} script_2.py", encoding='utf-8', timeout=10)
# 等待 READY 标记,确认 script_2 已初始化
child.expect("READY")
print("✓ script_2 启动完成")
# 发送用户输入(注意:无需额外换行,sendline 自动添加 \n)
message = input("Message to the other script: ")
child.sendline(message)
# 等待 DONE 标记,捕获中间所有输出(含 prompt 和 echo)
child.expect("DONE")
response = child.before.strip() # .before 包含从上一 expect 到当前匹配前的所有输出
print("← Received from script_2:", response)
child.close()
? 关键要点说明
- flush=True 是必需的:print(..., flush=True) 强制将缓冲区内容立即写入 stdout 管道,使 pexpect 能实时检测。
- 使用唯一、不可重复的 sync token:如 "READY" 和 "DONE",避免因用户输入中偶然出现相同字符串导致误匹配。
- encoding='utf-8' 提升健壮性:显式指定编码,防止字节/字符串混用错误(尤其在 Python 3.7+)。
- child.before 是响应主体:它包含 expect("DONE") 之前所有输出(包括 ">"、用户输入回显、"Echo: ..." 等),是获取对方响应的核心字段。
- 避免 input(">") 作为唯一同步点:其内部提示输出不可靠;应由被控脚本主动打印可控标记。
⚠️ 注意事项
- 路径问题:pexpect.spawn() 中的 Python 解释器路径建议使用 sys.executable,确保与当前环境一致;脚本路径需为绝对路径或确保工作目录正确。
- 超时设置:生产环境务必设置 timeout= 参数(如 timeout=5),防止子进程卡死导致主程序挂起。
- 错误处理:实际应用中应捕获 pexpect.TIMEOUT、pexpect.EOF 等异常,并做日志与清理(如 child.close())。
- 替代方案思考:若无硬性限制,multiprocessing.Pipe、queue.Queue 或 socket 更高效稳定;pexpect 主要适用于需要模拟终端交互的场景。
通过以上设计,两个脚本即可形成可靠的请求-响应闭环:主脚本发送消息 → 被控脚本接收、处理、输出响应 → 主脚本精准捕获结果。这是构建自动化测试、CLI 集成或复杂交互式工具链的坚实基础。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











