subprocess模块
Posted 东大网管
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了subprocess模块相关的知识,希望对你有一定的参考价值。
subprocess模块是
os.system作用os.system(cmd)的返回值只会有0(成功)
命令执行的返回值,0就是表示命令成功,非0表示命令失败(不一定是1)
但是我们想把命令的输出保存下来怎么操作呢?用函数os.popen("dir")
我们发现格式是乱的,我们现在print下这个结果:print就会把\\n弄成换行,变成好看了。
os.popen("dir").read() #会保存命令的执行结果输出
但是这个时候,没有返回的状态,不知道是否输出成功没。
在py2.7里,有commands模块,
commands.getstatusoutput("dir")可以得到返回结果是一个元祖,
第一个值就是执行命令的结果,
第二个是一个字符串,不过是字节类型二进制。
但是在win下执行commands这个模块是会报错的。返回执行结果是1,见上图。
在linux下是可以正常执行的。
res[0]返回的是成功的状态0,res[1]是命令返回的结果。
在python3里已经没有commands模块了:
os.spawn* 产生一个新进程
这两个模块的替换。上面这两个模块会慢慢被替换掉,逐步不使用了。
常用subprocess方法示例
subprocess.run(方法)
subprocess.run(["df","-h"]),写法奇特,注意有两个中刮号
如果你想执行命令,有管道的情况,就是有"| grep"的情况,就不能用这种一个一个参数传进去了:
要直接写在一个字符串里,而且后面要加一个参数shell=True
建议推荐使用.run()的方法~!
如果不涉及管道,那么就把命令当作一个列表,然后传进去。
如果涉及管道命令,那么就直接用一个字符串,然后参数shell=True来执行命令。
#执行命令,返回命令执行状态 , 0 or 非0
>>> retcode = subprocess.call(["ls", "-l"])
#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> subprocess.check_call(["ls", "-l"])
0
#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果
>>> subprocess.getstatusoutput(\'ls /bin/ls\')
(0, \'/bin/ls\')
这个方法跟 commands.getstatusoutput一样作用
一般我们都用这个方法足够了!!!
#接收字符串格式命令,并返回结果
>>> subprocess.getoutput(\'ls /bin/ls\')
\'/bin/ls\'
这个方法类似os.popen一样
#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res
>>> res=subprocess.check_output([\'ls\',\'-l\'])
>>> res
b\'total 0\\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\\n\'
#上面那些方法,底层都是封装的subprocess.Popen
poll()
Check if child process has terminated. Returns returncode
如果进程结束了,就返回执行代码。意思就是说这个命令的执行时间很长,你不知道啥时候结束,那么可以用这个方法,去查命令是否执行结束!
这个时候,我们可以不停的调用res.poll来查询这个命令是否结束:
而下面的wait()方法跟poll就不一样,它是一直等待到命令执行结束,然后返回命令执行的结果。
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate() 杀掉所启动进程
communicate() 等待任务结束
stdin 标准输入
stdout 标准输出
stderr 标准错误
pid
The process ID of the child process.
#例子
>>> p = subprocess.Popen("df -h|grep disk",stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
>>> p.stdout.read()
b\'/dev/disk1 465Gi 64Gi 400Gi 14% 16901472 104938142 14% /\\n\'
参数,stdout=subprocess.PIPE表示把数据先放到管道PIPE里,然后输出到屏幕,stderr=subprocess.PIPE把执行命令返回的错误放到管道里,然后输出到屏幕,stdin=subprocess.PIPE输入
subprocess.Popen()最大的好处,就是可以得到错误命令的输出结果!run只能得到正确的结果
调用subprocess.run(...)是推荐的常用方法,在大多数情况下能满足需求,但如果你可能需要进行一些复杂的与系统的交互的话,你还可以用subprocess.Popen(),语法如下:
可用参数:
- args:shell命令,可以是字符串或者序列类型(如:list,元组)
- bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
- stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
- preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
- close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。 - shell:同上
- cwd:用于设置子进程的当前目录,设置环境在哪个路径下执行脚本
- env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
- universal_newlines:不同系统的换行符不同,True -> 同意使用 \\n
- startupinfo与createionflags只在windows下有效
将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
终端输入的命令分为两种:
- 输入即可得到输出,如:ifconfig
- 输入进行某环境,依赖再输入,如:python
需要交互的命令示例
import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) obj.stdin.write(\'print 1 \\n \') obj.stdin.write(\'print 2 \\n \') obj.stdin.write(\'print 3 \\n \') obj.stdin.write(\'print 4 \\n \') out_error_list = obj.communicate(timeout=10) print out_error_list
subprocess实现sudo 自动输入密码
因为权限不够,想自动输入sudo的密码,现象如下图:
正常情况下,用一条命令来实现自动输入sudo密码:
以上是关于subprocess模块的主要内容,如果未能解决你的问题,请参考以下文章