subprocess模块

subprocess模块是

os.system作用os.system(cmd)的返回值只会有0(成功)

命令执行的返回值,0就是表示命令成功,非0表示命令失败(不一定是1)

但是我们想把命令的输出保存下来怎么操作呢?用函数os.popen("dir")

我们发现格式是乱的,我们现在print下这个结果:print就会把 弄成换行,变成好看了。

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 drwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM '

#上面那些方法,底层都是封装的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% / '

参数,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 -> 同意使用
      • 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 
 ')
obj.stdin.write('print 2 
 ')
obj.stdin.write('print 3 
 ')
obj.stdin.write('print 4 
 ')
 
out_error_list = obj.communicate(timeout=10)
print out_error_list

subprocess实现sudo 自动输入密码

 因为权限不够,想自动输入sudo的密码,现象如下图:

正常情况下,用一条命令来实现自动输入sudo密码:

原文地址:https://www.cnblogs.com/itfat/p/7499780.html