子进程管理
一句话
启动和管理子进程,连接输入输出管道,获取返回码。
什么时候翻这页
- Agent需要调用外部命令或工具时
- 需要捕获命令输出并结构化处理时
- 实现异步工具调用和超时控制时
- 替代旧有进程调用函数时
核心概念
- 进程管理:通过
subprocess模块可以创建新进程,控制其输入输出,并获取执行结果 - 管道通信:使用
PIPE创建与子进程的标准输入、输出和错误流的连接 - 返回码:子进程的退出状态码,0通常表示成功,非0表示出错
- 超时控制:通过
timeout参数限制命令执行时间,防止长时间阻塞 - 文本模式:通过
text或universal_newlines参数以文本而非二进制模式处理输入输出
怎么做
基本命令执行
# 简单执行命令,不捕获输出
subprocess.run(["ls", "-l"])
# 执行命令并捕获输出
result = subprocess.run(["ls", "-l", "/dev/null"], capture_output=True)
print(result.stdout) # 输出内容
print(result.returncode) # 返回码
带错误检查的执行
# 检查命令执行状态
try:
subprocess.run(["ls", "-l", "/nonexistent"], check=True)
except subprocess.CalledProcessError as e:
print(f"命令执行失败,返回码: {e.returncode}")
print(f"错误输出: {e.stderr}")
异步执行与超时处理
proc = subprocess.Popen(["long_running_command"])
try:
outs, errs = proc.communicate(timeout=15)
except subprocess.TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
print("命令执行超时")
管道连接
# 创建管道连接多个命令
p1 = subprocess.Popen(["dmesg"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "hda"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close() # 允许p1在p2退出时接收SIGPIPE
output = p2.communicate()[0]
命令 / API 速查
| 函数/类 | 描述 | 示例 |
|---|---|---|
subprocess.run() | 执行命令并等待完成 | subprocess.run(["ls", "-l"]) |
subprocess.Popen() | 创建子进程,更灵活的控制 | subprocess.Popen(["ls"]) |
subprocess.check_call() | 执行命令,检查返回码 | subprocess.check_call(["ls"]) |
subprocess.check_output() | 执行命令并返回输出 | subprocess.check_output(["ls"]) |
subprocess.PIPE | 创建管道连接 | stdout=subprocess.PIPE |
subprocess.DEVNULL | 使用空设备 | stderr=subprocess.DEVNULL |
subprocess.TimeoutExpired | 超时异常 | except subprocess.TimeoutExpired |
subprocess.CalledProcessError | 命令执行失败异常 | except subprocess.CalledProcessError |
与 Agent 开发的联系
- 工具调用实现:Agent可以使用subprocess模块调用外部工具和命令,扩展自身能力
- 结构化输出处理:通过捕获命令输出并解析,Agent可以将非结构化命令结果转换为结构化数据
- 异步执行:结合
Popen和communicate方法,Agent可以异步执行工具调用,避免阻塞主流程 - 超时控制:设置合理的超时时间,防止Agent被长时间运行的命令阻塞
- 错误处理:通过捕获和处理
CalledProcessError等异常,Agent可以优雅地处理工具调用失败的情况
初学者易错点
- 忘记处理命令执行失败的情况,特别是当
check=True时可能抛出CalledProcessError - 直接使用
.stdout.read()或.stdin.write()可能导致死锁,应使用communicate()方法 - 在Windows上使用
shell=True可能存在安全风险,应谨慎使用 - 忽略超时设置可能导致长时间运行的命令阻塞Agent响应
- 混淆文本模式和二进制模式,导致编码问题
相关词条
library-os- 操作系统接口,提供底层系统功能library-threading- 多线程支持,可用于并行处理多个子进程library-asyncio- 异步IO,提供更高级的异步执行能力library-shutil- 高级文件操作,常与subprocess配合使用library-shlex- shell命令解析,用于安全地构建命令参数