1. 程式人生 > >subprocess模塊

subprocess模塊

標準 encode .com ans 進行 size man try gpo

subprocess – 創建附加進程
subprocess
模塊提供了一種一致的方法來創建和處理附加進程,與標準庫中的其它模塊相比,提供了一個更高級的接口。用於替換如下模塊:
os.system() , os.spawnv() , os
和popen2模塊中的popen()函數,以及 commands().

1. 運行外部命令
subprocess.call(command)
方法
subprocess
的call方法可以用於執行一個外部命令,但該方法不能返回執行的結果,只能返回執行的狀態碼: 成功(0) 或 錯誤(非0)
call()
方法中的command可以是一個列表,也可以是一個字符串,作為字符串時需要用原生的shell來執行:

import subprocess

#執行 df -hl 命令

#方法1:

>>> subprocess.call([‘ls‘,‘-l‘])=subprocess.run("ls -l") #python3以後

total 8

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

0

#方法2:

>>> subprocess.call("ls -l",shell=True)

total 8

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

0

如上實例所示,雖然我們能看到執行的結果,但實際獲取的值只是狀態碼

>>> output = subprocess.call("ls -l",shell=True)

total 8

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

>>> print(output)

0

2. 錯誤處理
subprocess.check_call()

方法
我們說過call執行返回一個狀態碼,我們可以通過check_call()函數來檢測命令的執行結果,如果不成功將返回 subprocess.CalledProcessError 異常

>>> try:

subprocess.check_call("ls -t", shell=True)

except subprocess.CalledProcessError as err:

print("Command Error")

/bin/sh: lt: command not found

Command Error

3. 捕獲輸出結果
subprocess.check_output()
方法

call()方法啟動的進程,其標準輸入輸出會綁定到父進程的輸入和輸出。調用程序無法獲取命令的輸出結果。但可以通過check_output()方法來捕獲輸出。

# 以下測試為python3.4下運行結果

>>> output=subprocess.check_output("ls -l",shell=True)

>>> output

b‘total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n‘

>>> print(output.decode(‘utf-8‘))

total 8

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

以下例子將chek_output()方法執行命令異常時的錯誤捕獲,而避免輸出到控制臺.

try:

output = subprocess.check_output("lT -l", shell=True, stderr=subprocess.STDOUT)

except subprocess.CalledProcessError as err:

print("Command Error", err)

# 執行結果

Command Error Command ‘lT -l‘ returned non-zero exit status 127

直接處理管道
subprocess.Popen()
方法

函數call(), check_call() 和 check_output() 都是Popen類的包裝器。直接使用Popen會對如何運行命令以及如何處理其輸入輸出有更多控制。如通過為stdin, stdout和stderr傳遞不同的參數。

1. 與進程的單向通信
通過Popen()方法調用命令後執行的結果,可以設置stdout值為PIPE,再調用communicate()獲取結果
返回結果為tuple. 在python3中結果為byte類型,要得到str類型需要decode轉換一下

輸出結果(讀)

# 直接執行命令輸出到屏幕

>>> subprocess.Popen("ls -l",shell=True)

<subprocess.Popen object at 0x7febd4175198>

>>> total 12

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

-rw-rw-r-- 1 ws ws 8 Feb 25 10:38 test

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

# 不輸出到屏幕,輸出到變量

>>> proc = subprocess.Popen([‘echo‘,‘"Stdout"‘],stdout=subprocess.PIPE)

# communicate返回標準輸出或標準出錯信息

>>> stdout_value = proc.communicate()

>>> stdout_value

(b‘"Stdout"\n‘, None)

>>> proc = subprocess.Popen([‘ls‘,‘-l‘],stdout=subprocess.PIPE)

>>> stdout_value = proc.communicate()

>>> stdout_value

(b‘total 8\ndrwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem\ndrwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp\n‘, None)

>>>

>>> print((stdout_value[0]).decode(‘utf-8‘))

total 8

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

#將結果輸出到文件

>>> file_handle = open("/home/ws/t.log",‘w+‘)

>>> subprocess.Popen("ls -l",shell=True,stdout=file_handle)

t.log:

drwxrwxr-x 4 ws ws 4096 Nov 25 13:50 MonitorSystem

-rw-rw-r-- 1 ws ws 8 Feb 25 10:38 test

-rw-rw-r-- 1 ws ws 0 Feb 25 11:24 t.log

drwxrwxr-x 2 ws ws 4096 Feb 19 10:09 tmp

2 與進程的雙向通信

>>> proc = subprocess.Popen(‘cat‘, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

>>> msg = ‘Hello world‘.encode(‘utf-8‘)

# 寫入到輸入管道

>>> proc.stdin.write(msg)

11

>>> stdout_value = proc.communicate()

>>> stdout_value

(b‘Hello world‘, None)

# 在需要進行相互交互的輸入輸出過程也可以使用shtin來實現

# 以下實現打開python3的終端,執行一個print命令

>>>proc = subprocess.Popen([‘python3‘],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)

>>>proc.stdin.write(‘print("helloworld")‘.encode(‘utf-8‘))

>>>out_value,err_value=proc.communicate()

>>>print(out_value)

>>> print(out_value)

b‘helloworld\n‘

>>> print(err_value)

b‘‘

Popen.communicate()方法用於和子進程交互:發送數據到stdin,並從stdout和stderr讀數據,直到收到EOF。等待子進程結束。

捕獲錯誤輸出

>>> proc = subprocess.Popen([‘python3‘],stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,)

>>> proc.stdin.write(‘print "helloworld"‘.encode(‘utf-8‘))

18

>>> out_value,err_value=proc.communicate()

>>> out_value

b‘‘

>>> print(err_value.decode(‘utf-8‘))

File "<stdin>", line 1

print "helloworld"

^

SyntaxError: Missing parentheses in call to ‘print‘

Popen其它方法

1. Popen.pid 查看子進程ID

2. Popen.returncode 獲取子進程狀態碼,0表示子進程結束,None未結束

在使用Popen調用系統命令式,建議使用communicate與stdin進行交互並獲取輸出(stdout),這樣能保證子進程正常退出而避免出現僵屍進程。看下面例子

>>> proc = subprocess.Popen(‘ls -l‘, shell=True, stdout=subprocess.PIPE)

# 當前子進程ID

>>> proc.pid

28906

# 返回狀態為None,進程未結束

>>> print(proc.returncode)

None

# 通過communicate提交後

>>> out_value = proc.communicate()

>>> proc.pid

28906

# 返回狀態為0,子進程自動結束

>>> print(proc.returncode)

0

subprocess模塊