subprocess:
sub: 子
process: 進程python
能夠經過python代碼給操做系統發送命令,並將執行結果返回。shell
import subprocess while True: # 1.讓用戶輸入終端命令 cmd_str = input('請輸入終端命令:').strip() # Popen(cmd命令, shell=True, # stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 調用Popen就會將用戶的終端命令發送給本地操做系統的終端 # 獲得一個對象,對象中包含着正確或錯誤的結果。 obj = subprocess.Popen( cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) success = obj.stdout.read().decode('gbk') if success: print(success, '正確的結果') error = obj.stderr.read().decode('gbk') if error: print(error, '錯誤的結果')
subprocess模塊能夠生成新的進程,鏈接到它們的input/output/error管道,同時獲取它們的返回碼。函數
(1) args:啓動進程的參數,默認爲字符串序列(列表或元組),也可爲字符串(設爲字符串時通常需將shell參數賦值爲True);
(2) shell:shell爲True,表示args命令經過shell執行,則可訪問shell的特性;
(3) check:check爲True時,表示執行命令的進程以非0狀態碼退出時會拋出;subprocess.CalledProcessError異常;check爲False時,狀態碼爲非0退出時不會拋出異常;
(4) stdout、stdin、stderr:分別表示程序標準標輸出、輸入、錯誤信息;
run函數返回值爲CompletedProcess類,若需獲取執行結果,可經過獲取返回值的stdout和stderr來捕獲;
check_output函數若需捕獲錯誤信息,可經過stderr=subprocess.STDOUT來獲取;操作系統
# subprocess.run使用 def subprocess_run(): print("**** subprocess.run ****") print("----------") result1 = subprocess.run(["adb", "devices"]) print("result1:", result1) print("----------") result2 = subprocess.run("adb devices", shell=True, check=True) print("result2:", result2) print("----------") result3 = subprocess.run(["adb", "devices"], stdout=subprocess.PIPE) print("result3:", result3) print(type(result3)) subprocess_run() """結果 **** subprocess.run **** ---------- List of devices attached 338b123f0504 device result1: CompletedProcess(args=['adb', 'devices'], returncode=0) ---------- List of devices attached 338b123f0504 device result2: CompletedProcess(args='adb devices', returncode=0) ---------- result3: CompletedProcess(args=['adb', 'devices'], returncode=0, stdout=b'List of devices attached \r\n338b123f0504\tdevice\r\n\r\n') <class 'subprocess.CompletedProcess'> """ # subprocess.call使用 def subprocess_call(): print("**** subprocess.call ****") print("----------") result1 = subprocess.call(["adb", "devices"]) print("result1:", result1) print("----------") result2 = subprocess.call(["adb", "devices"], stdout=subprocess.PIPE) print("result2:", result2) subprocess_call() """結果 **** subprocess.call **** ---------- List of devices attached 338b123f0504 device result1: 0 ---------- result2: 0 """ # subprocess.check_call def subprocess_check_call(): print("**** subprocess.check_call ****") print("----------") result1 = subprocess.check_call(["adb", "devices"]) print("result1:", result1) print("----------") result2 = subprocess.check_call(["adb", "devices"], stdout=subprocess.PIPE) print("result2:", result2) subprocess_check_call() """結果 **** subprocess.check_call **** ---------- List of devices attached 338b123f0504 device result1: 0 ---------- result2: 0 """ # subprocess.check_output def subprocess_check_output(): print("**** subprocess.check_output ****") print("----------") result1 = subprocess.check_output(["adb", "devices"]) print("result1:", result1) print("----------") result2 = subprocess.run(["adb", "devices"], stdout=subprocess.PIPE).stdout print("result2:", result2) subprocess_check_output() """結果 **** subprocess.check_output **** ---------- result1: b'List of devices attached \r\n338b123f0504\tdevice\r\n\r\n' ---------- result2: b'List of devices attached \r\n338b123f0504\tdevice\r\n\r\n' """
cmd:參數,字符串類型;code
# subprocess.getoutput或getstatusoutput使用 def subprocess_get_output(): print("**** subprocess.getoutput ****") result1 = subprocess.getoutput("adb devices") print("result1:", result1) print(type(result1)) print("**** subprocess.getstatusoutput ****") result2 = subprocess.getstatusoutput("adb devices") print("result2:", result2) print(type(result2)) subprocess_get_output() """結果 **** subprocess.getoutput **** result1: List of devices attached 338b123f0504 device <class 'str'> **** subprocess.getstatusoutput **** result2: (0, 'List of devices attached \n338b123f0504\tdevice\n') <class 'tuple'> """
subprocess.Popen類用於在一個新進程中執行一個子程序,上述subprocess函數均是基於subprocess.Popen類;對象
- args:須要執行的系統命令,可爲字符串序列(列表或元組,shell爲默認值False便可,建議爲序列),也可爲字符串(使用字符串時,需將shell賦值爲True);
- shell:默認爲False,若args爲序列時,shell=False;若args爲字符串時,shell=True,表示經過shell執行命令;
- stdout、stdin、stderr:分別表示子程序標準輸出、標準輸入、標準錯誤,可爲subprocess.PIPE、一個有效的文件描述符、文件對象或None。
若爲subprocess.PIPE:表明打開通向標準流的管道,建立一個新的管道;
若爲None:表示沒有任何重定向,子進程會繼承父進程;
stderr也可爲subprocess.STDOUT:表示將子程序的標準錯誤輸出重定向到了標準輸出- bufsize:指定緩衝策略,0表示不緩衝,1表示行緩衝,其它整數表示緩衝區大小,負數表示使用系統默認值0;
- cwd:默認值爲None;若非None,則表示將會在執行這個子進程以前改變當前工做目錄;
- env:用於指定子進程的環境變量。若env爲None,那麼子進程的環境變量將從父進程中繼承;若env非None,則表示子程序的環境變量由env值來設置,它的值必須是一個映射對象。
- universal_newlines: 不一樣系統的換行符不一樣。若True,則該文件對象的stdin,stdout和stderr將會以文本流方式打開;不然以二進制流方式打開。
def subprocess_Popen1(): print("***經過communicate函數分別輸出PopenObject對象的輸出流和錯誤流***") args = [["adb", "devices"], ["adb", "devices11"]] for arg in args: popen_object = subprocess.Popen(arg, stdout=subprocess.PIPE, stderr=subprocess.PIPE) object_stdout, object_stderr = popen_object.communicate() output = {"popen_object": popen_object, "object_stdout": object_stdout, "object_stderr": object_stderr} print(output) """ {'popen_object': <subprocess.Popen object at 0x0000000002212400>, 'object_stdout': b'List of devices attached \r\n106D111805005938\tdevice\r\n\r\n', 'object_stderr': b''} {'popen_object': <subprocess.Popen object at 0x0000000002577C18>, 'object_stdout': b'', 'object_stderr': b'Android Debug Bridge version 1.0.31\r\n\r\n -a .....} """ print("***經過stdout和stderr方法輸出PopenObject對象輸出流和錯誤流***") p0 = subprocess.Popen(["adb", "devices"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) object_stdout = p0.stdout.read() p0.stdout.close() object_stderr = p0.stderr.read() p0.stderr.close() print(object_stdout) # 結果:b'List of devices attached \r\n338b123f0504\tdevice\r\n\r\n' print(object_stderr) # 結果:b'' print("***Popen對象stdin寫入功能:使用stdout和stderr輸出") args = ["python", "python1"] for arg in args: p4 = subprocess.Popen([arg], shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p4.stdin.write("print('hello')") p4.stdin.close() out = p4.stdout.read() p4.stdout.close() err = p4.stderr.read() p4.stderr.close() print("out:%s err:%s" % (out, err)) """ ***Popen對象stdin寫入功能 out:hello err: out: err:'python1' 不是內部或外部命令,也不是可運行的程序或批處理文件。 """ print("***Popen對象stdin寫入功能:使用communicate輸出") p4 = subprocess.Popen(["python"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p4.stdin.write("print('hello')") output = p4.communicate() print(output) # 結果:('hello\n', '') print("***不含encoding參數***") p1 = subprocess.Popen("adb devices", shell=True, stdout=subprocess.PIPE) out1 = p1.stdout.readlines() print(out1) # 結果: [b'List of devices attached \r\n', b'106D111805005938\tdevice\r\n', b'\r\n'] print("***含encoding參數***") p2 = subprocess.Popen("adb devices", shell=True, stdout=subprocess.PIPE, encoding="utf-8") out2 = p2.stdout.readlines() print(out2) # 結果: ['List of devices attached \n', '106D111805005938\tdevice\n', '\n'] print("***Popen對象檢查命令是否結束,等待進程結束") print(p2.poll()) # 結果: None print(p2.wait()) # 結果: 0 print(p2.poll()) # 結果: 0 print("***Popen對象communicate函數,它會阻塞父進程直至子進程完成") p3 = subprocess.Popen("adb devices", shell=True, stdout=subprocess.PIPE) out = p3.communicate()[0] print(out) # 結果:b'List of devices attached \r\n338b123f0504\tdevice\r\n\r\n' print(p3.poll()) # 結果:0 subprocess_Popen1() def subprocess_Popen2(): """ 1. 經過管道功能,實現adb shell ps | findstr top功能 2. 直接爲args賦值爲一個字符串,實現adb shell ps | findstr top功能 :return: """ print("***經過管道方式***") p1 = subprocess.Popen(["adb", "shell", "ps"], stdout=subprocess.PIPE) p2 = subprocess.Popen(["findstr", "top"], stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p2.communicate() print(out, err) # 結果:b'shell 8508 8504 2600 1044 c004e5f8 b6f40938 S top\r\r\n' b'' print("***經過傳一個字符串方式***") p3 = subprocess.Popen("adb shell ps | findstr top", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p3.communicate() print(out, err) # 結果:b'shell 8508 8504 2600 1044 c004e5f8 b6f40938 S top\r\r\n' b'' subprocess_Popen2()