python调用linux命令输出结果,Python-运行shell命令并捕获输出
小編典典
這個問題的答案取決于你使用的Python版本。最簡單的方法是使用以下subprocess.check_output功能:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
該check_output功能適用于仍在廣泛使用的幾乎所有版本的Python(2.7+)。2但對于較新的版本,不再推薦使用此方法。
現代版本的Python(3.5或更高版本): run
如果你使用的是Python 3.5或更高版本,并且不需要向后兼容,則建議使用新run功能。它為該subprocess模塊提供了非常通用的高級API 。要捕獲程序的輸出,請將subprocess.PIPE標志傳遞給stdout關鍵字參數。然后訪問stdout返回CompletedProcess對象的屬性:
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
返回值是一個bytes對象,因此,如果你需要正確的字符串,則需要decode它。假設被調用的進程返回一個UTF-8編碼的字符串:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
所有這些都可以壓縮為一種格式:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
如果要將輸入傳遞給流程的stdin,bytes請將一個對象傳遞給input關鍵字參數:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
你可以通過傳遞stderr=subprocess.PIPE(捕獲到result.stderr)或stderr=subprocess.STDOUT(捕獲到result.stdout常規輸出)來捕獲錯誤。如果不考慮安全性,你還可以shell=True按照下面的說明通過傳遞來運行更復雜的Shell命令。
與舊的工作方式相比,這僅增加了一點復雜性。但是我認為值得這樣做:現在,你僅需使用該run功能就可以完成幾乎所有需要做的事情。
舊版本的Python(2.7-3.4): check_output
如果你使用的是舊版本的Python,或者需要適度的向后兼容性,則可以使用check_output上面簡要介紹的函數。自python 2.7開始可用。
subprocess.check_output(*popenargs, **kwargs)
它采用與Popen(請參見下文)相同的參數,并返回一個包含程序輸出的字符串。該答案的開頭有一個更詳細的用法示例。在Python 3.5及更高版本中,check_output等效于run使用check=True和stdout=PIPE,僅返回stdout屬性。
你可以通過stderr=subprocess.STDOUT確保錯誤信息包含在返回的輸出-但在Python中通過一些版本stderr=subprocess.PIPE,以check_output可引起死鎖。如果不考慮安全性,你還可以shell=True按照下面的說明通過傳遞來運行更復雜的Shell命令。
如果你需要通過管道stderr傳遞輸入或將輸入傳遞給流程,check_output則將無法完成任務。Popen在這種情況下,請參見下面的示例。
復雜的應用程序和Python的舊版(2.6及以下版本): Popen
如果需要深度向后的兼容性,或者需要比check_output提供的功能更復雜的功能,則必須直接使用Popen對象,這些對象封裝了用于子流程的低級API。
所述Popen構造器接受單個命令沒有參數,或列表包含指令作為其第一項,其次是任意數量的參數,每個作為列表一個單獨的項目。shlex.split可以幫助將字符串解析為格式正確的列表。Popen對象還接受用于進程IO管理和低級配置的許多不同參數。
發送輸入和捕獲輸出communicate幾乎始終是首選方法。如:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
要么
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
如果設置stdin=PIPE,communicate還允許你通過以下方式將數據傳遞到流程stdin:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
注艾倫·霍爾的回答,這表明在某些系統上,你可能需要設置stdout,stderr以及stdin所有PIPE(或DEVNULL)得到communicate工作的。
在極少數情況下,你可能需要復雜的實時輸出捕獲。Vartec的答案提出了一條前進的道路,但是communicate如果不謹慎使用,則其他方法都容易出現死鎖。
與上述所有功能一樣,當不考慮安全性時,可以通過傳遞運行更復雜的Shell命令shell=True。
筆記
1.運行shell命令:shell=True參數
通常,對run,check_output或Popen構造函數的每次調用都會執行一個程序。這意味著沒有花哨的bash風格的管道。如果要運行復雜的Shell命令,則可以傳遞shell=True,這三個功能都支持。
但是,這樣做會引起安全問題。如果你要做的不僅僅是輕腳本編寫,那么最好單獨調用每個進程,并將每個進程的輸出作為輸入通過以下方式傳遞給下一個進程:
run(cmd, [stdout=etc...], input=other_output)
要么
Popen(cmd, [stdout=etc...]).communicate(other_output)
直接連接管道的誘惑力很強;抵抗它。否則,你可能會遇到僵局,或者不得不做類似此類的駭人聽聞的事情。
2. Unicode注意事項
check_output在Python 2中返回一個字符串,但bytes在Python 3中返回一個對象。如果還沒有,則花一點時間來學習unicode。
2020-02-06
總結
以上是生活随笔為你收集整理的python调用linux命令输出结果,Python-运行shell命令并捕获输出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 平行世界是什么意思 平行世界解释
- 下一篇: linux useradd 数字,详解l