Python學習--subprocess

一、subprocess 模塊簡介

subprocess最早是在2.4版本中引入的。
subprocess模塊用來生成子進程,並可以通過管道連接它們的輸入/輸出/錯誤,以及獲得它們的返回值。
它用來代替多箇舊模塊和函數:
os.system
os.spawn*
os.popen*
popen2.*
commands.*


1.1. 使用 subprocess模塊

啓動子進程的推薦方式是使用下面的便利功能。
當這些還不能滿足需求時,就需要使用底層的Popen接口。

1. subprocess.call

語法:
     subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
語義:
     運行由args指定的命令,直到命令結束後,返回 返回碼的屬性值。

示例代碼:
>>> subprocess.call(["ls", "-l"])
0
>>> subprocess.call("exit 1", shell=True)
1

WARNING: 使用 shell=True 是一種安全保護機制。
NOTE: 在使用這個函數時,不要使用 stdout=PIPE 或 stderr=PIPE 參數,
      不然會導致子進程輸出的死鎖。
      如果要使用管道,可以在 communicate()方法中使用Popen
      
示例代碼:
import subprocess
rc = subprocess.call(["ls","-l"])


通過一個shell來解釋一整個字符串:

import subprocess
out = subprocess.call("ls -l", shell=True)
out = subprocess.call("cd ..", shell=True)

使用了shell=True這個參數。
這個時候,我們使用一整個字符串,而不是一個表來運行子進程。
Python將先運行一個shell,再用這個shell來解釋這整個字符串。

shell命令中有一些是shell的內建命令,這些命令必須通過shell運行,$cd。
shell=True允許我們運行這樣一些命令。


2. subprocess.check_call

語法: 
     subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
語義:
     運行由args指定的命令,直到命令執行完成。
     如果返回碼爲零,則返回。否則,拋出 CalledProcessError異常。
     CalledProcessError對象包含有返回碼的屬性值。

上面顯示的參數僅僅是最常見的,下面是用戶更常用的參數。
示例代碼如下:

>>>
>>> subprocess.check_call(["ls", "-l"])
0
>>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
   ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

這個函數在python 2.5版本中引入。
WARNING: 使用 shell=True 是一種安全機制。
NOTE: 不要在這個函數中使用 stdout=PIPE 或 stderr=PIPE, 否則會造成子進程死鎖。
      如果需要使用管道,可以在 communicate()方法中使用Popen.


3. subprocess.check_output

語法: 
      subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
語義:
     運行args定義的命令,並返回一個字符串表示的輸出值。
     如果返回碼爲非零,則拋出 CalledProcessError異常。
示例代碼:
>>>
>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
>>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
   ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
如果要捕捉結果中的標準錯誤,使用 stderr=subprocess.STDOUT參數:
>>>
>>> subprocess.check_output(
...     "ls non_existent_file; exit 0",
...     stderr=subprocess.STDOUT,
...     shell=True)
'ls: non_existent_file: No such file or directory\n'

這個函數在python 2.7版本中引入。
WARNING: 使用 shell=True 是一種安全機制。
NOTE: 不要在這個函數中使用 stdout=PIPE 或 stderr=PIPE, 否則會造成子進程死鎖。
      如果需要使用管道,可以在 communicate()方法中使用Popen.


4.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 -> 同意使用 \n

·startupinfo與createionflags只在windows下有效
將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等

import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2", shell=True)

終端輸入的命令分爲兩種:

·輸入即可得到輸出,如:ifconfig

·輸入進行某環境,依賴再輸入,如:python

import subprocess

obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()print(cmd_out)print(cmd_error)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")

out_error_list = obj.communicate()print(out_error_list)
import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out_error_list = obj.communicate('print("hello")')
print(out_error_list)

要注意的是,communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成。

可以利用communicate()方法來使用PIPE給子進程輸入:

import subprocess
child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
child.communicate("vamei")

啓動子進程之後,cat會等待輸入,直到我們用communicate()輸入"vamei"。



詳文參見:http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html

http://blog.chinaunix.net/uid-26000296-id-4461522.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章