subprocess.Popen用法
背景:
最近需要抓取一个程序的运行log,但发现os.popen去执行程序,只能抓取到标准输出的log,错误输出的log没法抓取到。导致只能想其他办法,后发现subprocess库的Popen方法解决了这个问题,所以特此来归纳学习一下
subprocess介绍:
subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值
Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。
构造函数:
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)
下面挑选一些常用参数来说明
args
agrs参数可以接收三种形式的值:
1、程序参数的序列(以list的形式)
subprocess.Popen(['python','test.py'])
2、字符串
subprocess.Popen('python test.py')
3、(可执行文件的)路径
subprocess.Popen('test.bat')
shell
参数 shell (默认为 False)指定是否使用 shell 执行程序。如果 shell 为 True,更推荐将 args 作为字符串传递而非序列。
在 POSIX,当 shell=True, shell 默认为 /bin/sh。如果 args 是一个字符串,此字符串指定将通过 shell 执行的命令。这意味着字符串的格式必须和在命令提示符中所输入的完全相同。这包括,例如,引号和反斜杠转义包含空格的文件名。如果 args 是一个序列,第一项指定了命令,另外的项目将作为传递给 shell (而非命令) 的参数对待。
在 Windows,使用 shell=True,环境变量 COMSPEC 指定了默认 shell。在 Windows 你唯一需要指定 shell=True 的情况是你想要执行内置在 shell 中的命令(例如 dir 或者 copy)。在运行一个批处理文件或者基于控制台的可执行文件时,不需要 shell=True
当你需要使用 shell 中特有的命令时,需要加上 shell=True
stdin,stdout,stderr
stdin:标准输入
stdout:标准输出
stderr:标准错误
合法的值有PIPE,DEVNULL,一个存在的文件描述符(一个正整数),一个存在的文件对象,以及None
PIPE:为文本流提供一个缓存区,可将stdin、stdout、stderr的文件都输出到缓存去中
DEVNULL:等同/dev/null,表示输出内容全部丢弃不保存
例子:
import subprocess sbpss = subprocess.Popen('python test.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE) print(sbpss.stdout.read()) print(sbpss.stderr.read())
输出如下:
如果想同时捕获标准输出和标准错误输出,可以将stderr设置为subprocess.STDOUT,表示将stderr标准错误输出重定向到stdout标准输出中,同时标准输出又重定向到PIPE中
下面我将shell打开,然后故意将echo写错为ech,就会输出标准错误
import subprocess
sbpss = subprocess.Popen('ech test',shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
print(sbpss.stdout.read())
打印如下:
可以看到上面输出都是byte形式,无法直观看到输出,可以用以下3个方法解决
1、encoding=''
import subprocess
sbpss = subprocess.Popen('echo 你好',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding='gbk')
print(sbpss.stdout.read())
2、decode()
import subprocess
sbpss = subprocess.Popen('echo 你好',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print(sbpss.stdout.read().decode('gbk'))
3、text=True(推荐,不需要考虑编码格式)
import subprocess
sbpss = subprocess.Popen('echo 你好',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True) print(sbpss.stdout.read())
cwd
用于设置子进程的当前目录
如下:需要在其它路径下创建一个文件夹
import subprocess sbpss = subprocess.Popen('mkdir test',shell=True,cwd='D:\prj_test\subprocess_test')
可以看到已经在D:\prj_test\subprocess_test下新建了一个test文件夹
env
为子进程设置环境变量,默认为None,子进程的环境变量从父进程中继承
env 参数的值必须是一个字典类型。设置了 env 参数之后,不仅可以在命令中使用,也可以在 bat 或者 sh 脚本中使用
import subprocess sbpss = subprocess.Popen('echo %name% 是 %gender%的',shell=True,stdout=subprocess.PIPE,text=True,env={'name':'小明','gender':'男'}) print(sbpss.stdout.read())
输出如下
注意,示例代码中环境变量的写法是 windows系统的写法,在 unix 环境下你应该使用 $name来替代%name%
communicate(input,timeout)方法
有的时候,我们需要在子进程中实现一些输入,子进程才能进行下一步,此时就需要用到communicate()方法,将输入传输到子进程之中
###name.py### name = input('what is name?\n') print(f'hi,{name}') import subprocess sbpss = subprocess.Popen('python name.py',shell=True,stdin=subprocess.PIPE)
sbpss.communicate('xiaoming'.encode('utf-8'))
输出结果:
在name.py中,使用input方法来接收用户输入,同时在popen中设置stdin参数为一个通道,这样就用可以通过communicate('xiaoming'.encode('utf-8')),来传入用户的输入到子进程中,子进程接着向下执行
communicate 方法返回两个值,文档里面说到这两个值分别为 stdout 以及 stderr。当你在 Popen 参数中设置了二者为 PIPE 时,就可以返回相应的结果了,否则将会输出两个 None
import subprocess sbpss = subprocess.Popen('python name.py',shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) out,err = sbpss.communicate('xiaoming'.encode('utf-8')) print('标准输出:'+out.decode()) print('标准错误:'+err.decode())
输出结果:
returncode属性
对于一个进程来说,在其结束时往往会返回一个 exit code,通常情况下,code 为 0 表示一切正常,否则就是出现错误。
在 Popen 中,同样也有 returncode 来返回子程序的 exit code。不过这个值必须要在 communicate 方法之后才能获取到
import subprocess sbpss = subprocess.Popen('echo hi',shell=True) print(sbpss.returncode) sbpss.communicate() print(sbpss.returncode)
参考资料:https://ld246.com/article/1577762914087、https://www.runoob.com/w3cnote/python3-subprocess.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界