python3中使用subprocess模块执行外部命令
一. subprocess模塊介紹
subprocess模塊可以替代os模塊下的os.system和os.popen等操作方法
subprocess模塊在python2和python3上的使用上有一定的區別,本文主要介紹的是在python3.6上的使用
subprocess模塊的作用是執行外部命令(支持同步執行和異步執行),可以返回執行狀態碼,也可以返回執行內容
subprocess模塊的方法有很多,最核心的方法為subprocess.Popen方法,python3中如果只需要同步執行,優先使用subprocess.run方法
二. subprocess.run()方法的介紹
2.1 執行代碼:在windows下執行一條cmd命令
# -*- coding:utf-8 -*- # Author:chinablueimport subprocess# 在windows下執行cmd命令:echo hello dj p = subprocess.run("echo hello dj", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print(f'獲取返回對象: {p}') print(f'獲取執行命令:{p.args}') print(f'獲取返回碼:{p.returncode}') print(f'獲取返回數據:{p.stdout}')2.2 執行結果:
獲取返回對象: CompletedProcess(args='echo hello dj', returncode=0, stdout=b'hello dj\r\n', stderr=b'') 獲取執行命令:echo hello dj 獲取返回碼:0 獲取返回數據:b'hello dj\r\n'2.3 分析小結:
1 ) subprocess.run()方法是一個同步方法,執行后會返回一個CompletedProcess對象
2 ) 通過管道可以捕獲子進程的標準輸出(stdout)和標準錯誤(stderr)
如果使用的是python3.7及以上版本,可以使用capture_output=True參數替換stdout=subprocess.PIPE和stderr=subprocess.PIPE參數
p = subprocess.run("echo hello dj", shell=True, capture_output=True) print(f'獲取返回數據:{p.stdout}') # 執行結果:獲取返回數據:b'hello dj\r\n'將執行結果輸出到一個文件中去
# 將命令的執行結果輸出到output.txt文件中 # 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 # 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! with open("output.txt", "w") as f:p1 = subprocess.run("dir", shell=True, stdout=f, universal_newlines=True, encoding="utf-8")3 ) 默認情況下,獲取的返回數據(stdxxx)為字節類型。
通過universal_newlines=True參數可以讓返回數據以文本字符串輸出
p = subprocess.run("echo hello dj", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) print(f'獲取返回數據:{p.stdout}') # 運行結果:獲取返回數據:hello dj如果使用的是python3.7及以上版本, 可以使用text=True參數替換universal_newlines=True參數
p = subprocess.run("echo hello dj", shell=True, capture_output=True, text=True) print(f'獲取返回數據:{p.stdout}') # 運行結果:獲取返回數據:hello dj如果不使用universal_newlines=True參數或text=True參數,我們也可以對p.stdout進行解碼轉換
p = subprocess.run("echo hello dj", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print(f'獲取返回數據:{p.stdout.decode("gbk")}') # 注意:windows下需要使用gbk解碼 # 運行結果:獲取返回數據:hello dj4 ) 關于返回狀態碼的說明
如果命令執行成功,returncode返回0; 如果命令執行失敗,returncode返回負值
check=True參數會自動檢查p.returncode是否返回0, 如果不是0就拋出subprocess.CalledProcessError異常
p = subprocess.run("echo1", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True) print(f'獲取返回數據:{p.stdout}')如果不使用 check=True參數,我們可以通過p.returncode來做判斷條件, 進而打印出詳細錯誤p.stderr
# 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 # 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! p = subprocess.run("echo1", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) if p.returncode !=0:print(f'命令執行失敗:{p.stderr}')三. subprocess.Popen()方法的介紹
subprocess.run()是通過subprocess.Popen()來實現的
subprocess.Popen()可以異步執行
3.1 執行代碼:在windows下執行一條cmd命令
# -*- coding:utf-8 -*- # 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 # 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書!import subprocess# 在windows下執行cmd命令:echo chinablue p = subprocess.Popen("echo chinablue", shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) print(f"獲取返回對象: {p}") print(f"獲取pid: {p.pid}") print(f"獲取返回數據: {p.stdout.read()}") p.wait() print(f"獲取執行狀態: {p.poll()}")3.2 執行結果:
獲取返回對象: <subprocess.Popen object at 0x0028C4B0> 獲取pid: 5260 獲取返回數據: chinablue 獲取執行狀態: 03.3 分析小結:
1 ) subprocess.Popen()方法是一個異步方法,執行后會返回一個Popen對象
2 ) 獲取子進程的標準輸出(stdout)和標準錯誤(stderr)
方式1:通過p.stdout和p.stderr獲取,如上例所示
方式2:通過p.communicate()獲取,它返回一個元祖,元祖的第1個元素為stdout內容,元祖的第2個元素為stderr內容
p = subprocess.Popen("echo chinablue", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) print(f"獲取返回數據: {p.communicate()[0]}") print(f"獲取返回錯誤: {p.communicate()[1]}")3 ) 獲取命令的執行狀態:p.poll()
如果執行完subprocess.Popen()方法后,立即獲取命令的執行狀態, 則返回結果為None,因為此時子進程扔在運行中
如果我們需要等待子進程運行完畢后,再去獲取命令的執行狀態。那么我們可以使用p.wait()方法,這相當于將默認的異步操作改為同步操作
p = subprocess.Popen("echo chinablue", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) print(p.poll()) # 運行結果: None p.wait() print(p.poll()) # 運行結果: 0四. 常見場景舉例
場景1:在windows下,執行ipconfig命令并對結果進行過濾
# -*- coding:utf-8 -*- # 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 # 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! import subprocess# 步驟1:將ipconfig命令的執行結果寫入output.txt文件 with open("output.txt", "w") as f:subprocess.run("ipconfig", shell=True, stdout=f, universal_newlines=True, encoding="utf-8") # 步驟2:將p1的輸出內容作為p2的輸入內容 p1 = subprocess.run("type output.txt", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p2 = subprocess.run("findstr IPv4", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, input=p1.stdout) print(p2.stdout)場景2:在windows下,模擬并發執行命令
# -*- coding:utf-8 -*- # 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:778463939 # 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! import time import subprocess# 模擬一條耗時命令,此命令在windows下執行相當于sleep 2s cmd = "ping -n 3 127.0.0.1 > nul"start_time = time.time() p1 = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p2 = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p1.wait() p2.wait() print(f"運行時間共計:{int(time.time() - start_time)}s") # p1和p2命令執行各需耗時2s,通過并發執行后共計耗時也是2s場景3:自動處理命令行交互
# -*- coding: utf-8 -*- import subprocess# 這是一條對視頻文件進行處理的命令(改變視頻分辨率,同時將視頻設置為倍速播放) cmd = f'ffmpeg -i "dj_xiaomi.mp4" -s vga -filter:v "setpts=0.5*PTS" output.mp4' p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)# 命令在執行過程中,如果本地已經存在有output.mp4文件, 那么命令行處會出現提示符: File 'output.mp4' already exists. Overwrite? [y/N] buff = '' while True:output = p.stdout.read(1)if output:buff += outputelse:break# 出現提示符([y/N])后,程序可以自行處理此交互行為if buff.endswith("[y/N]"):p.communicate(input="y")break另外python中的pexpect模塊更擅長解決命令行的自動交互問題
總結
以上是生活随笔為你收集整理的python3中使用subprocess模块执行外部命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python教程:对 a = [lamb
- 下一篇: python中将函数赋值给变量时需要注意