Intro
The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.
即subprocess支持我们从当前进程生成子进程来执行command,虽然都是生成子程序,但是和fork不同,subprocess更specified于执行一个执行shell命令的子程序。
Use
subprocess.run(args,*,stdin=None,stdout=None,stderr=None,shell=False,
text=None,cwd=None,input=None,timeout=None)
该函数会spawn一个用于执行args的子进程,并返回一个CompletedProcess对象.
- args可以是一个列表,也可以是一个string,如: ["ls","-l"]或"pwd".注意当args为string时,它只能单纯的指定一个可执行文件,不能带任何参数,除非指定shell参数为True.( If passing a single string, either shell must be True or else the string must simply name the program to be executed without specifying any arguments.)
- stdin、stdout、stderr执行了子进程的标准输入、输出、错误流,一般只有stdout和stderr会被用到,如不指定stdout,则标准输出会被直接打印在屏幕上,一般使用subprocess.PIPE这个管道来指定stdout,而对于stderr则是subprocess.STDOUT,这样标准输出、错误会被暂存在管道中,并可由CompletedProcess对象取出.
- shell参数则是配和args使用,如果args是string则最好把shell置为True.
- text参数:If text mode is not used, stdin, stdout and stderr will be opened as binary streams. No encoding or line ending conversion is performed.
- cwd参数指定一个path,使得子进程在args所代表的shell命令执行前先cd到指定的path下
- input传递给Popen.communicate
- timeout传递给Popen.communicate
对于subprocess.run返回的CompletedProcess对象,它有一些attributes可以方便我们获得子进程执行命令的情况.
- returncode 获得子进程的返回值,0为成功执行.
- args 子进程对应的args
- stdout 假如在subprocess.run函数调用时指定PIPE的话,这里会从管道中得到stdout结果,否则为None.
- stderr 和stdout同理
不过,作为module级的函数,它实质上其实是通过class level的一些类和方法实现的,即是subprocess.Popen和Popen.communicate等.
subprocess.Popen(args,stdin=None,stdout=None,stderr=None,shell=False,
cwd=None,text=None)
使用该类时会创建一个子进程执行args并返回一个Popen实例对象.下面介绍该类的一些method:
- poll 该方法check子进程是否结束,假如结束返回returncode,否则返回None.
- terminate 该方法终结子进程
- kill 该方法杀死子进程,与terminate的区别在于传递的SIGNAL的不同,terminate的结束更加politely,在windows上的两者则无区别.
- wait(timeout=None) 父进程等待子进程结束,超过timeout则报错,raise a TimeExpired exception.
- communicate(input=None,timeout=None) 该方法是与子进程进行沟通,即向input传递数据,timeout和上面相同,returns a tuple (stdout_data, stderr_data). The data will be strings if streams were opened in text mode; otherwise, bytes.
Popen的一些attributes:
- stdin、stdout、stderr和之前的CompletedProcess同理
- returncode 实例对应的子进程的返回值
- args 实例对应的子进程的命令
- pid 实例对应的子进程的pid
Cautions
Popen.wait will deadlock when using stdout=PIPE or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use Popen.communicate() when using pipes to avoid that. 即Popen使用PIPE的时候最好不要使用wait方法,否则可能会引起deadlock,使用communicate会避免这一点。
对于subprocess.run函数所创建的子进程,父进程会自动等待子进程结束,而如果单独使用subprocess.Popen,则父进程不会等待,可以使用Popen.wait,不过上文已经不建议使用该函数,不过其实Popen.communicate除了Interact with process的作用,还有Wait for process to terminate,所以上文才提到使用commnunicate替代wait+Popen.stdout,Popen.stderr.