subprocess

可以创建新的进程,可以与新建进程的输入/输出/错误管道连通,并可以获得新建进程执行的返回状态. 使用subprocess模块的目的是替代os.system()、os.popen*()、commands.*等旧的函数或模块。

注意: 当执行命令的参数或者返回中包含了中文文字,那么建议使用subprocess,如果使用os.popen则会出现错误

1. subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

执行args 描述的命令, 等待命令完成,然后返回returncode属性。

不要使用stdout=PIPE或stderr=PIPE,基于子进程的输出流量可能导致死锁。需要管道时,使用Popen和它的communicate()方法

  • demo
>>> subprocess.call(["ls", "-l"])
0

>>> subprocess.call("exit 1", shell=True)
1

1.1. 经常用到的参数

  • args

一个字符串或者一个程序参数的序列。一般倾向于提供一个参数的序列,让该模块来处理参数的转义和引用(例如允许文件名中包含空格)。 如果传递一个单一的字符串,shell必须为True,或者该字符串必须不带任何参数

  • stdin、stdout 和stderr

分别指定程序的标准输入、标准输出和标准错误文件的句柄。

合法的值有PIPE、一个已经存在的文件描述符(一个正整数)、一个已经存在的文件对象和None。 PIPE表示应该为子进程创建一个新的管道。如果为默认设置None,则不会发生重定向;子进程的文件句柄将从父进程中继承。

stderr 可以为STDOUT,表示来自子进程中标准错误的数据捕获到和标准输出相同的文件中。

当stdout 或者stderr 为管道时且universal_newlines 为True,那么所有的行结束符将被转换成'\n' ,正如open()的universal newlines 'U' 模式参数所描述的一样。

  • shell

shell=True,则指定的命令将通过shell执行。方便地访问shell功能,例如shell 管道、文件名通配符、环境变量的扩展以及~访问某个用户的home目录

2. subprocess.check_call

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

执行带参数的命令, 等待命令完成。如果返回码是则返回,否则抛出CalledProcessError, 返回码在returncode属性中。

不要使用stdout=PIPE或stderr=PIPE,基于子进程的输出流量可能导致死锁。需要管道时,使用Popen和它的communicate()方法

3. subprocess.check_output

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

执行带参数的命令并将它的输出作为字节字符串返回。如果返回码非零,引发CalledProcessError, 返回码保存在returncode属性中并把任何输出都保存在output属性中。

不要使用stdout=PIPE或stderr=PIPE,基于子进程的输出流量可能导致死锁。需要管道时,使用Popen和它的communicate()方法

  • demo
In [2]: subprocess.check_output(['echo', '123'])
Out[2]: '123\n'

# 结果中捕获标准错误,可以使用 stderr=subprocess.STDOUT:
In [15]: subprocess.check_output( "ls ff; exit 0", stderr=subprocess.STDOUT, shell=True)
Out[15]: "ls: cannot access 'ff': No such file or directory\n"

4. subprocess.Popen

class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

在Unix上,shell=True,默认为/bin/sh

  • demo
# 替换shell 的管道
# output=`dmesg | grep hda`
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
# Allow p1 to receive a SIGPIPE if p2 exits.
p1.stdout.close()          
output = p2.communicate()[0]

# or
output=check_output("dmesg | grep hda", shell=True)

# communicate()方法来使用PIPE给子进程输入:
import subprocess
child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
child.communicate("vamei")

import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)        # args正确的分词
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args)
  • Popen 类的实例
Popen.poll()    检查子进程是否已经终止。设置并返回returncode属性。
Popen.wait()    等待子进程终止。设置并返回returncode属性。
Popen.communicate(input=None) 与进程交互:将数据发送到标准输出。从标准输出和标准错误读取数据,直至到达文件末尾。等待进程终止。
        可选的input 参数应该是一个要发送给子进程的字符串,如果没有数据要发送给子进程则应该为None。
        communicate()返回一个元组(stdoutdata, stderrdata)。
        该方法会阻塞父进程,直到子进程完成
Popen.send_signal(signal)    发送信号signal 给子进程。
Popen.terminate()    终止子进程
Popen.kill()        杀死子进程

# 下面的属性也可以访问, 
# 使用communicate()而不要用.stdin.write、.stdout.read 或.stderr.read,避免由于其它操作系统管道缓存填满并阻塞子进程引起的死锁。
Popen.stdin        如果stdin 参数为PIPE,则该属性为一个文件对象,它提供子进程的输入。
            否则,为None。
Popen.stdout        如果stdout 参数为PIPE,则该属性是一个文件对象,提供子进程中的输出。
            否则,为None。
Popen.stderr        如果stderr 参数为PIPE,则该属性是一个文件对象,提供子进程中的错误输出。
            否则,为None。
Popen.pid        子进程的进程ID。shell为True,为产生的shell的进程ID。
Popen.returncode    子进程的返回码, None值表示子进程还没有终止。
            负值-N表示子进程被信号N终止(Unix)。

5. 0x01 os

5.1. os.system()

不返回shell命令的输出

In [28]: os.system('ls')
tmp
Out[28]: 0

5.2. os.popen()

返回输出结果

>>>tmp = os.popen('ls *.sh').readlines()  
>>>tmp  
['install_zabbix.sh\n', 'manage_deploy.sh\n', 'mysql_setup.sh\n', 'python_manage_deploy.sh\n', 'setup.sh\n']

6. 0x02 commands

可以很方便的取得命令的输出(包括标准和错误输出)和执行状态位

6.1. commands.getstatusoutput(cmd)

返回(status,output)

import commands
a,b = commands.getstatusoutput('ls')
a是退出状态
b是输出的结果。
>>> import commands
>>> a,b = commands.getstatusoutput('ls')
>>> print a
0
>>> print b
anaconda-ks.cfg
install.log
install.log.syslog

6.2. commands.getoutput(cmd)

只返回输出结果

results matching ""

    No results matching ""