欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

subprocess模塊怎么使用

阮建安2年前17瀏覽0評論

subprocess模塊怎么使用?

subprocess 模塊主要用于創(chuàng)建子進程,并連接它們的輸入、輸出和錯誤管道,獲取它們的返回狀態(tài)。通俗地說就是通過這個模塊,你可以在 python 的代碼里執(zhí)行操作系統(tǒng)級別的命令,比如ipconfig、du -sh等。

subprocess 模塊替代了一些老的模塊和函數(shù),比如:os.system、os.spawn*等。

subprocess 過去版本中的call(),check_call()和check_output()已經(jīng)被run()方法取代了。run()方法為 3.5 版本新增。

大多數(shù)情況下,推薦使用run()方法調(diào)用子進程,執(zhí)行操作系統(tǒng)命令。在更高級的使用場景,你還可以使用 Popen 接口。其實run()方法在底層調(diào)用的就是 Popen 接口。

subprocess.run

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None)

功能:執(zhí)行 args 參數(shù)所表示的命令,等待命令結(jié)束,并返回一個 CompletedProcess 類型對象。

注意,run() 方法返回的不是我們想要的執(zhí)行結(jié)果或相關(guān)信息,而是一個 CompletedProcess 類型對象。

上面參數(shù)表里展示的只是一些常用的,真實情況還有很多。

args:表示要執(zhí)行的命令,必須是一個字符串,字符串參數(shù)列表。

stdin、stdout 和 stderr:子進程的標(biāo)準(zhǔn)輸入、輸出和錯誤。其值可以是subprocess.PIPE、subprocess.DEVNULL、一個已經(jīng)存在的文件描述符、已經(jīng)打開的文件對象或者 None。

subprocess.PIPE表示為子進程創(chuàng)建新的管道,subprocess.DEVNULL表示使用os.devnull。默認(rèn)使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起輸出。

timeout:設(shè)置命令超時時間。如果命令執(zhí)行時間超時,子進程將被殺死,并彈出TimeoutExpired異常。

check:如果該參數(shù)設(shè)置為 True,并且進程退出狀態(tài)碼不是 0,則彈出CalledProcessError異常。

encoding:如果指定了該參數(shù),則 stdin、stdout 和 stderr 可以接收字符串?dāng)?shù)據(jù),并以該編碼方式編碼。否則只接收 bytes 類型的數(shù)據(jù)。

shell:如果該參數(shù)為 True,將通過操作系統(tǒng)的 shell 執(zhí)行指定的命令。

看下面的例子:

>>> subprocess.run(["ls", "-l"]) # 沒有對輸出進行捕獲 CompletedProcess(args=['ls', '-l'], returncode=0) >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE) CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n') >>> subprocess.run("python --version", stdout=subprocess.PIPE) CompletedProcess(args='python --version', returncode=0, stdout=b'Python 3.6.1\r\n') >>>s= subprocess.run("ipconfig", stdout=subprocess.PIPE) # 捕獲輸出 >>>print(s.stdout.decode("GBK"))

subprocess.CompletedProcess

run() 方法的返回值,表示一個進程結(jié)束了。CompletedProcess類有下面這些屬性:

args 啟動進程的參數(shù),通常是個列表或字符串。

returncode 進程結(jié)束狀態(tài)返回碼。0表示成功狀態(tài)。

stdout 獲取子進程的 stdout。通常為 bytes 類型序列,None 表示沒有捕獲值。如果你在調(diào)用 run() 方法時,設(shè)置了參數(shù)stderr=subprocess.STDOUT,則錯誤信息會和 stdout 一起輸出,此時 stderr 的值是 None。

stderr 獲取子進程的錯誤信息。通常為 bytes 類型序列,None 表示沒有捕獲值。

check_returncode() 用于檢查返回碼。如果返回狀態(tài)碼不為零,彈出CalledProcessError異常。

subprocess.DEVNULL

一個特殊值,用于傳遞給 stdout、stdin 和 stderr 參數(shù)。表示使用os.devnull作為參數(shù)值。

subprocess.PIPE

管道,可傳遞給 stdout、stdin 和 stderr 參數(shù)。

subprocess.STDOUT

特殊值,可傳遞給 stderr 參數(shù),表示 stdout 和 stderr 合并輸出。

args 與 shell

args 參數(shù)可以接收一個類似'du -sh'的字符串,也可以傳遞一個類似['du', '-sh']的字符串分割列表。shell 參數(shù)默認(rèn)為 False,設(shè)置為 True 的時候表示使用操作系統(tǒng)的 shell 執(zhí)行命令。

下面我們來看一下兩者的組合結(jié)果。

In [14]: subprocess.run('du -sh') --------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) ...... FileNotFoundError: [Errno 2] No such file or directory: 'du -sh' In [15]: subprocess.run('du -sh', shell=True) 175M . Out[15]: CompletedProcess(args='du -sh', returncode=0)

可見,在 Linux 環(huán)境下,當(dāng) args 是個字符串時,必須指定 shell=True。成功執(zhí)行后,返回一個CompletedProcess 對象。

In [16]: subprocess.run(['du', '-sh'], shell=True) .....大量的數(shù)據(jù) 4 ./文檔 179100 . Out[16]: CompletedProcess(args=['du', '-sh'], returncode=0) In [17]: subprocess.run(['du', '-sh']) 175M . Out[17]: CompletedProcess(args=['du', '-sh'], returncode=0)

可見,當(dāng)args是一個['du', '-sh']列表,并且shell=True的時候,參數(shù)被忽略了,只執(zhí)行不帶參數(shù)的du命令。

總結(jié):Linux 中,當(dāng) args 是個字符串是,請設(shè)置 shell=True,當(dāng) args 是個列表的時候,shell 保持默認(rèn)的 False。

獲取執(zhí)行結(jié)果

run() 方法返回的是一個 CompletedProcess 類型對象,不能直接獲取我們通常想要的結(jié)果。要獲取命令執(zhí)行的結(jié)果或者信息,在調(diào)用 run() 方法的時候,請指定 stdout=subprocess.PIPE。

>>> ret = subprocess.run('dir', shell=True) >>> ret CompletedProcess(args='dir', returncode=0) >>> ret = subprocess.run('dir', shell=True, stdout=subprocess.PIPE) >>> ret CompletedProcess(args='dir', returncode=0, stdout=b' \xc7\xfd\xb6\xaf\xc6\xf7 ......') >>> ret.stdout b' \xc7\xfd\xb6\xaf\xc6\xf7 C \xd6\xd0\xb5\xc4\xbe\xed\xca\xc7 ......'

從例子中我們可以看到,如果不設(shè)置stdout=subprocess.PIPE,那么在返回值CompletedProcess(args='dir', returncode=0)中不會包含 stdout 屬性。反之,則會將結(jié)果以 bytes 類型保存在 ret.stdout 屬性中。

交互式輸入

并不是所有的操作系統(tǒng)命令都像‘dir’或者‘ipconfig’那樣單純地返回執(zhí)行結(jié)果,還有很多像‘python’這種交互式的命令,你要輸入點什么,然后它返回執(zhí)行的結(jié)果。使用run()方法怎么向stdin里輸入?

這樣?

import subprocess ret = subprocess.run("python", stdin=subprocess.PIPE, stdout=subprocess.PIPE,shell=True) ret.stdin = "print('haha')" # 錯誤的用法 print(ret)

這樣是不行的,ret作為一個CompletedProcess對象,根本沒有stdin屬性。那怎么辦呢?前面說了,run()方法的stdin參數(shù)可以接收一個文件句柄。比如在一個1.txt文件中寫入print('i like Python')。然后參考下面的使用方法:

import subprocess fd = open("d:\\1.txt") ret = subprocess.run("python", stdin=fd, stdout=subprocess.PIPE,shell=True) print(ret.stdout) fd.close()

這樣做,雖然可以達(dá)到目的,但是很不方便,也不是以代碼驅(qū)動的方式。這個時候,我們可以使用Popen類。

subprocess.Popen()

用法和參數(shù)與run()方法基本類同,但是它的返回值是一個Popen對象,而不是CompletedProcess對象。

>>> ret = subprocess.Popen("dir", shell=True) >>> type(ret) <class 'subprocess.Popen'> >>> ret <subprocess.Popen object at 0x0000000002B17668>

Popen對象的stdin、stdout和stderr是三個文件句柄,可以像文件那樣進行讀寫操作。

>>>s = subprocess.Popen("ipconfig", stdout=subprocess.PIPE, shell=True) >>>print(s.stdout.read().decode("GBK"))

要實現(xiàn)前面的‘python’命令功能,可以按下面的例子操作:

import subprocess s = subprocess.Popen("python", stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) s.stdin.write(b"import os\n") s.stdin.write(b"print(os.environ)") s.stdin.close() out = s.stdout.read().decode("GBK") s.stdout.close() print(out)

通過s.stdin.write()可以輸入數(shù)據(jù),而s.stdout.read()則能輸出數(shù)據(jù)。