可惜了!!!!
之前一直用os.popen/os.system來執行作業系統的指令,很繁瑣,今天了解到了subprocess這個子產品,感覺很強大,比os.popen/os.system強太多了,學習分享出來。
The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:
該
subprocess
子產品允許您生成新程序,連接配接到它們的input/output/error 管道,并擷取它們的傳回代碼。該子產品旨在替換幾個較舊的子產品和功能(如:os.system/os.spawn*)
run函數原型:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
The recommended approach to invoking subprocesses is to use the
run()
function for all use cases it can handle. For more advanced use cases, the underlying
Popen
interface can be used directly.
大多數情況下推薦使用
run()
方法調用子程序執行作業系統指令。在更進階的使用場景,可以直接使用底層的popen接口.
是以大多數情況下,隻要熟悉run()方法的使用就夠了。
Run the command described by args. Wait for command to complete, then return a CompletedProcessinstance.
另,run()函數傳回的是一個CompletedProcess執行個體對象
來自 <https://docs.python.org/3/library/subprocess.html>
方法 | 描述 |
args | 字元串或者清單 |
stdin stdout stderr | None 子程序的輸入 PIPE 建立管道, 如設定為PIPE, 則capture_output預設為false即可,會輸出stdout值 PIPE建立管道, 如設定為PIPE, 則capture_output預設為false即可,會輸出stderr值 |
capture_output | False(default)/True, 如果capture_output為true,則将捕獲stdout和stderr |
encoding | 如果指定了該參數,則stdin、stdout和stderr可以接收字元串資料,并以該編碼方式編碼。否則隻接收bytes類型的資料 如encoding="utf-8" |
shell | 如果該參數為True,将通過作業系統的shell執行指定的指令。 unix下相當于args前面添加了 "/bin/sh“ ”-c” window下,相當于添加"cmd.exe /c" |
cwd | 設定工作目錄 |
env | 設定環境變量 |
subprocess.CompletedProcess
run()方法的傳回值, 傳回一個CompletedProcess對象,其屬性如下:
方法 | 描述 |
args | 字元串或者清單 |
returncode | 退出子程序的狀态碼。通常,退出狀态為0表示它已成功運作。 |
stdout | 擷取子程序的stdout。為bytes類型,None表示沒有捕獲值。如果調用run()方法時,設定了參數stderr=subprocess.STDOUT,則stderr會和stdout一起輸出,此時stderr的值是None |
stderr | 擷取子程序的stderr。為bytes類型,None表示沒有捕獲值 |
check_returncode | If returncode is non-zero, raise a CalledProcessError. |
以下是一些應用執行個體:
import subprocess
# 應用subprocess擷取裝置清單, 相對于之前的寫法感覺更友善,注釋的是之前的寫法
def getdevlist():
devlist = []
# connectfile = os.popen('adb devices')
# list = connectfile.readlines()
result_list = subprocess.run('adb devices', capture_output=True, encoding='utf-8').stdout.strip().split('\n')
# for i in range(len(list)):
for info in result_list:
# if list[i].find('\tdevice') != -1:
if info.find('\tdevice') != -1:
# temp = list[i].split('\t')
temp = info.split('\t')
devlist.append(temp[0])
return devlist
def main():
# 列印出結果,但devstr1.stdout為空
devstr1 = subprocess.run('adb devices')
print(f'devstr1: {devstr1}')
# 列印出結果,結果中有捕獲stdout/stderr值,但類型為bytes
devstr2 = subprocess.run('adb devices', capture_output=True)
print(f'devstr2: {devstr2}')
# 列印出結果,結果中有捕獲stdout/stderr值,類型為str, 因為有指定encoding=‘utf-8'
devstr3 = subprocess.run('adb devices', capture_output=True, encoding='utf-8')
print(f'devstr3: {devstr3}')
# 列印出結果,結果中有捕獲stdout值,類型為str, 因為有指定encoding=‘utf-8'
devstr4 = subprocess.run('adb devices', stdout=subprocess.PIPE, encoding='utf-8')
print(f'devstr4: {devstr4}')
# 列印出結果,結果中有捕獲stdout/stderr值,類型為str, 因為有指定encoding=‘utf-8', 此時不再再設定capture_output=True
devstr5 = subprocess.run('adb devices', stderr=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf-8')
print(f'devstr5: {devstr5}')
print(f'目前Pc連接配接的裝置如下:\n{getdevlist()}')
if __name__ == '__main__':
main()
-----------the result of pycharm---------------------------------------------------
List of devices attached
ad17caf5 device
devstr1: CompletedProcess(args='adb devices', returncode=0)
devstr2: CompletedProcess(args='adb devices', returncode=0, stdout=b'List of devices attached\r\nad17caf5\tdevice\r\n\r\n', stderr=b'')
devstr3: CompletedProcess(args='adb devices', returncode=0, stdout='List of devices attached\nad17caf5\tdevice\n\n', stderr='')
devstr4: CompletedProcess(args='adb devices', returncode=0, stdout='List of devices attached\nad17caf5\tdevice\n\n')
devstr5: CompletedProcess(args='adb devices', returncode=0, stdout='List of devices attached\nad17caf5\tdevice\n\n', stderr='')
目前Pc連接配接的裝置如下:
['ad17caf5']
Process finished with exit code 0