subprocess-About-简介

subprocess 模块用来创建新的进程,连接到其stdin、stdout、stderr管道并获取它们的返回码。

subprocess模块的出现是为了替代旧模块及函数:os.systemos.spawn*os.popen*popen2.*commands.*

强烈建议POSIX用户(Linux、BSD等)安装并使用较新的subprocess32模块,而不是Python 2.7自带的subprocess。

推荐用户使用callcheck_callcheck_output这三个快捷函数,在无法满足需求的时候才使用更高级的Popen接口。

subprocess.call-调用

call函数可以认为是对popenwait的分装,直接对call函数传入要执行的命令行,将命令行的退出code返回。

运行由args参数提供的命令,等待命令执行结束并返回返回码。args参数由字符串形式提供且有多个命令参数时,

需要提供shell=True参数:

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

注意不要为stdout和stderr参数赋值subprocess.PIPE,如果子进程输出量较多会造成死锁,这两个参数可以赋值为subprocess.STDOUT打印到屏幕或者赋值为一个文件对象将输出写入文件:

1
2
3
//test.py-示例
import subprocess as sp
sp.call('python run.py', shell = True, stdin=open('fake_input', 'r'), stdout=open('result', 'w'))

subprocess.check_call-调用返回确认

与call方法类似,不同在于如果命令行执行成功,check_call返回返回码0,否则抛出subprocess.CalledProcessError异常。

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

subprocess.check_output-调用输出确认

在子进程执行命令,以字符串形式返回执行结果的输出。如果子进程退出码不是0,抛出subprocess.CalledProcessError异常,异常的output字段包含错误输出:

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

subprocess.Popen 管道调用

开启新进程

Popen启动新的进程与父进程并行执行,默认父进程不等待新进程结束。

1
2
3
4
5
def TestPopen():
import subprocess
p=subprocess.Popen("dir",shell=True)
for i in range(250) :
print ("other things")

等待子进程结束

p.wait函数使得父进程等待新创建的进程运行结束,然后再继续父进程的其他任务。且此时可以在p.returncode中得到新进程的返回值。

1
2
3
4
5
6
7
8
def TestWait():
import subprocess
import datetime
print (datetime.datetime.now())
p=subprocess.Popen("sleep 10",shell=True)
p.wait()
print (p.returncode)
print (datetime.datetime.now())

poll等待

p.poll函数可以用来检测新创建的进程是否结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
def TestPoll():
import subprocess
import datetime
import time
print (datetime.datetime.now())
p=subprocess.Popen("sleep 10",shell=True)
t = 1
while(t <= 5):
time.sleep(1)
p.poll()
print (p.returncode)
t+=1
print (datetime.datetime.now())

结束进程

p.killp.terminate用来结束创建的新进程,在windows系统上相当于调用TerminateProcess(),在posix系统上相当于发送信号SIGTERM和SIGKILL。

1
2
3
4
5
6
7
8
9
10
def TestKillAndTerminate():
p=subprocess.Popen("notepad.exe")
t = 1
while(t <= 5):
time.sleep(1)
t +=1
p.kill()
#p.terminate()
print ("new process was killed")

与子进程交互

p.communicate可以与新进程交互,但是必须要在popen构造时候将管道重定向。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def TestCommunicate():
import subprocess
cmd = "dir"
p=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(stdoutdata, stderrdata) = p.communicate()
if p.returncode != 0:
print (cmd + "error !")
#defaultly the return stdoutdata is bytes, need convert to str and utf8
for r in str(stdoutdata,encoding='utf8' ).split("\n"):
print (r)
print (p.returncode)
def TestCommunicate2():
import subprocess
cmd = "dir"
#universal_newlines=True, it means by text way to open stdout and stderr
p = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
curline = p.stdout.readline()
while(curline != ""):
print (curline)
curline = p.stdout.readline()
p.wait()
print (p.returncode)