天天看點

built-in:subprocess子產品的用法

可惜了!!!!

之前一直用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