1. 程式人生 > >Python subprocess模組解析

Python subprocess模組解析

在學習這個模組前,我們先用Python的help()函式檢視一下subprocess模組是幹嘛的:

DESCRIPTION
    This module allows you to spawn processes, connect to their
    input/output/error pipes, and obtain their return codes. 

即允許你去建立一個新的程序讓其執行另外的程式,並與它進行通訊,獲取標準的輸入、標準輸出、標準錯誤以及返回碼等。
注意:使用這個模組之前要先引入該模組。

Popen類

subprocess模組中定義了一個Popen類,通過它可以來建立程序,並與其進行復雜的互動。檢視一下它的建構函式:

__init__(self, 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)

主要引數說明:
args:args should be a string, or a sequence of program arguments.也就是說必須是一個字串或者序列型別(如:字串、list、元組),用於指定程序的可執行檔案及其引數。如果是一個序列型別引數,則序列的第一個元素通常都必須是一個可執行檔案的路徑。當然也可以使用executeable引數來指定可執行檔案的路徑。

stdin,stdout,stderr:分別表示程式的標準輸入、標準輸出、標準錯誤。有效的值可以是PIPE,存在的檔案描述符,存在的檔案物件或None,如果為None需從父程序繼承過來,stdout可以是PIPE,表示對子程序建立一個管道,stderr可以是STDOUT,表示標準錯誤資料應該從應用程式中捕獲並作為標準輸出流stdout的檔案控制代碼。

shell:如果這個引數被設定為True,程式將通過shell來執行。
env:它描述的是子程序的環境變數。如果為None,子程序的環境變數將從父程序繼承而來。

建立Popen類的例項物件

res = subprocess.Popen(cmd, shell
=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

cmd:標準像子程序傳入需要執行的shell命令,如:ls -al

subprocess.PIPE:在建立Popen物件時,subprocess.PIPE可以初始化為stdin, stdout或stderr的引數,表示與子程序通訊的標準輸入流,標準輸出流以及標準錯誤。

subprocess.STDOUT:作為Popen物件的stderr的引數,表示將標準錯誤通過標準輸出流輸出。

Popen類擁有的方法及屬性

1、Popen.pid
獲取子程序的程序ID。

2、Popen.returncode
獲取程序的返回碼。如果程序未結束,將返回None。

3、communicate(input=None)
官方解釋:

Interact with process: Send data to stdin.  Read data from
stdout and stderr, until end-of-file is reached.  Wait for
process to terminate.  The optional input argument should be a
string to be sent to the child process, or None, if no data
should be sent to the child.

communicate() returns a tuple (stdout, stderr).

與子程序進行互動,像stdin傳送資料,並從stdout和stderr讀出資料存在一個tuple中並返回。
引數input應該是一個傳送給子程序的字串,如果未指定資料,將傳入None。

4、poll()
檢查子程序是否結束,並返回returncode屬性。

5、wait()

Wait for child process to terminate.  Returns returncode attribute.

等待子程序執行結束,並返回returncode屬性,如果為0表示執行成功。

6、send_signal( sig)

Send a signal to the process

傳送訊號給子程序。

7、terminate()

Terminates the process

終止子程序。windows下將呼叫Windows API TerminateProcess()來結束子程序。

8、kill()
官方文件對這個函式的解釋跟terminate()是一樣的,表示殺死子程序。

程序通訊例項1

開啟一個只有ip地址的文字檔案,讀取其中的ip,然後進行ping操作,並將ping結果寫入ping.txt檔案中。
首先建立一個子程序res,傳入要執行的shell命令,並獲得標準輸出流、返回碼等。

import subprocess
import os
class Shell(object) :
  def runCmd(self, cmd) :
    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    sout ,serr = res.communicate() 
    return res.returncode, sout, serr, res.pid

shell = Shell()
fp = open('c:\\test\\ip.txt', 'r')
ipList = fp.readlines()
fp.close()
fp = open('c:\\test\\ping.txt', 'a')
print ipList
for i in ipList :
  i = i.strip()
  result = shell.runCmd('ping ' + i)
  if result[0] == 0 :
    w = i + ' : 0'
    fp.write(w + '\n')
  else :
    w = i + ' : 1'
    fp.write(w + '\n')

fp.close()

執行結果:

1

程序通訊例項2

命令互動,不斷從鍵盤接受命令執行,給出執行結果,直到使用者輸入exit或者bye退出命令互動。

import subprocess
class Shell(object) :
  def runCmd(self, cmd) :
    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    sout ,serr = res.communicate()     
    return res.returncode, sout, serr, res.pid

shell = Shell()
while 1 :
  input = raw_input('>')
  if input == 'exit' or input == 'bye' :
    break
  else :
    result = shell.runCmd(input)
    print "返回碼:", result[0]
    print "標準輸出:", result[1]
    print "標準錯誤:", result[2]

在Windows上也可以使用os.system()這個函式來執行一些dos命令,但是這個命令只能拿到返回碼,拿不到標準輸出,標準錯誤,所以通常使用的subprocess模組中的Popen類來實現。