subprocess.Popen全面解析与进程通信
请全面介绍subprocess.Popen的用法,包括创建子进程、管道通信(stdin/stdout/stderr)、communicate()的阻塞与非阻塞、poll()与wait()的区别、returncode以及超时处理。
回答
小字辈
Popen基本用法
import subprocess
# 运行命令
proc = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
# 管道通信
stdout, stderr = proc.communicate(timeout=10)
print(stdout.decode())
关键参数
args: 命令序列(推荐列表形式),或字符串(需shell=True)stdin/subprocess.PIPE: 管道输入stdout/subprocess.PIPE: 管道输出stderr/subprocess.STDOUT: 合并到stdoutcwd: 工作目录env: 环境变量字典universal_newlines=True: 自动文本模式(Python 3.7+用text=True)
communicate() vs 直接读写
- communicate(): 读写管道并等待进程结束(内置防止死锁)
out, err = proc.communicate(input=b'data', timeout=30)适合一次读完。data量太大时可能内存溢出。
poll() vs wait()
- poll(): 非阻塞,检查子进程状态。若未完成返回
None,已完成返回退出码while proc.poll() is None: print('正在运行...') time.sleep(0.1) - wait(): 阻塞等待子进程结束,返回退出码
returncode = proc.wait(timeout=30)
超时处理
try:
outs, errs = proc.communicate(timeout=15)
except subprocess.TimeoutExpired:
proc.kill()
outs, errs = proc.communicate() # 收集剩余输出
returncode属性
None: 进程仍在运行0: 成功- 负数: 被信号终止(如
-9表示SIGKILL)