Python 進(jìn)程調(diào)用(subprocess)的實(shí)現(xiàn)
1. 概述
1.1. subprocess 簡(jiǎn)介
在 Python 編程中,subprocess 庫(kù)是一個(gè)功能強(qiáng)大的工具,它允許我們創(chuàng)建新進(jìn)程、連接到其輸入/輸出/錯(cuò)誤管道,并獲取其返回代碼。
1.2. subprocess 庫(kù)的功能
subprocess 庫(kù)提供了多種功能,以滿足不同的需求。主要功能包括:
- 運(yùn)行外部命令: 可以執(zhí)行系統(tǒng)命令或調(diào)用其他可執(zhí)行文件。
- 交互式進(jìn)程通信: 啟動(dòng)外部進(jìn)程,并通過(guò)管道與其進(jìn)行交互,發(fā)送輸入并獲取輸出。
- 管道和重定向: 創(chuàng)建一個(gè)進(jìn)程的輸出作為另一個(gè)進(jìn)程的輸入,或重定向進(jìn)程的輸出到文件。
- 進(jìn)程管理: 監(jiān)控進(jìn)程狀態(tài),等待進(jìn)程結(jié)束,或終止進(jìn)程。
2. 應(yīng)用場(chǎng)景及示例
2.1. 運(yùn)行外部命令
subprocess.run() 是一個(gè)高級(jí)接口,用于執(zhí)行外部命令并等待其完成。它返回一個(gè) CompletedProcess 對(duì)象,包含執(zhí)行結(jié)果的相關(guān)信息。
import subprocess
import sys
def run_command_safely(command):
"""安全運(yùn)行命令,處理Windows和Unix的差異"""
try:
if sys.platform == 'win32':
# Windows 需要特殊處理
result = subprocess.run(command, shell=True, capture_output=True, text=True, encoding='gbk')
else:
# Unix/Linux/Mac
result = subprocess.run(command, capture_output=True, text=True)
return result
except Exception as e:
return subprocess.CompletedProcess(command, 1, '', str(e))
result = run_command_safely(['ls'])
# # 執(zhí)行外部命令并捕獲輸出
print("Return Code:", result.returncode)
print("Standard Output:", result.stdout)
print("Standard Error:", result.stderr)
capture_output=True:捕獲子進(jìn)程的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤。
text=True:以文本模式處理輸入/輸出。
2.2. 交互式進(jìn)程通信
subprocess.Popen() 提供了更靈活的方式來(lái)管理子進(jìn)程,可以通過(guò)管道發(fā)送輸入數(shù)據(jù)給子進(jìn)程,并獲取其輸出。
import subprocess
import sys
def basic_popen(command):
"""基本Popen使用"""
try:
if sys.platform == 'win32':
# 執(zhí)行dir命令
result = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding='gbk')
else:
result = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)
except Exception as e:
return subprocess.CompletedProcess(command, 1, '', str(e))
# 等待進(jìn)程完成并獲取輸出
stdout, stderr = result.communicate()
# return result
print(f"返回碼: {result.returncode}")
print(f"輸出:\n{stdout}")
if stderr:
print(f"錯(cuò)誤:\n{stderr}")
basic_popen(['dir'])
[‘dir’]:要執(zhí)行的命令和參數(shù)。
stdin=subprocess.PIPE:通過(guò)管道向子進(jìn)程發(fā)送數(shù)據(jù)。
stdout=subprocess.PIPE:通過(guò)管道捕獲子進(jìn)程的輸出。
process.communicate(input=‘some input data\n’):向子進(jìn)程發(fā)送輸入數(shù)據(jù)并獲取輸出。
2.3. 管道和重定向
subprocess 庫(kù)可以輕松創(chuàng)建管道,將一個(gè)進(jìn)程的輸出重定向到另一個(gè)進(jìn)程的輸入。
import subprocess
# 第一個(gè)命令
p1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
# 第二個(gè)命令,通過(guò)管道傳輸數(shù)據(jù)
p2 = subprocess.Popen(['grep', '.py'], stdin=p1.stdout, stdout=subprocess.PIPE)
output = p2.communicate()[0]
print('Python文件列表:')
print(output.decode())
p1.stdout=subprocess.PIPE:將p1的輸出作為管道。
p2.stdin=p1.stdout:將p1的輸出作為p2的輸入。
p2.communicate():獲取p2的最終輸出。
2.4. 進(jìn)程管理
subprocess.Popen() 還提供了多種方法來(lái)管理進(jìn)程,如poll()、terminate()、kill()等。
import subprocess
import sys
def run_command_safely(command):
"""安全運(yùn)行命令,處理Windows和Unix的差異"""
try:
if sys.platform == 'win32':
# Windows 需要特殊處理
result = subprocess.Popen(command, shell=True, text=True, encoding='gbk')
else:
# Unix/Linux/Mac
result = subprocess.Popen(command)
# 檢查進(jìn)程是否仍在運(yùn)行
print("Process is running:", result.poll() is None)
# 終止進(jìn)程
result.terminate()
# 等待進(jìn)程結(jié)束
result.wait()
print("Process has terminated")
except Exception as e:
print("Exception", str(e))
return subprocess.CompletedProcess(command, 1, '', str(e))
# 啟動(dòng)一個(gè)子進(jìn)程
run_command_safely(['sleep', '10'])
process.poll():檢查進(jìn)程是否仍在運(yùn)行,返回None表示仍在運(yùn)行,返回退出碼表示已結(jié)束。
process.terminate():請(qǐng)求終止進(jìn)程。
process.wait():等待進(jìn)程結(jié)束。
3. 與 os.system 和 os.popen 對(duì)比
雖然 os.system 和 os.popen 也可以用于執(zhí)行外部命令并與進(jìn)程進(jìn)行交互,但它們與 subprocess 相比存在一些限制和不足。
3.1. os.system
os.system 是 Python 中最簡(jiǎn)單的執(zhí)行外部命令的方法,但它有幾個(gè)顯著的缺點(diǎn):
無(wú)法捕獲輸出: os.system 只能執(zhí)行命令,無(wú)法直接捕獲其輸出或錯(cuò)誤。輸出會(huì)直接打印到控制臺(tái)。
返回碼有限: 它返回一個(gè)8位的字節(jié),表示命令的退出狀態(tài),這可能導(dǎo)致?tīng)顟B(tài)碼被截?cái)唷?br />安全性問(wèn)題: 使用字符串拼接來(lái)構(gòu)建命令可能會(huì)導(dǎo)致安全風(fēng)險(xiǎn),如命令注入。
import os
# 執(zhí)行外部命令
exit_code = os.system('dir')
print("Exit Code:", exit_code)
3.2. os.popen
os.popen 允許我們打開(kāi)一個(gè)與命令的管道,從中讀取輸出。與 os.system 相比,它可以捕獲輸出,但仍然有一些限制:
單向通信: 它只能用于從命令讀取輸出,不能發(fā)送輸入。
資源管理: 需要手動(dòng)關(guān)閉文件對(duì)象,否則可能導(dǎo)致資源泄漏。
安全性問(wèn)題: 同樣存在命令注入的風(fēng)險(xiǎn)。
import os
# 打開(kāi)一個(gè)與命令的管道并讀取輸出
process = os.popen('dir')
output = process.read()
process.close()
print("Output:", output)
3.3. subprocess 的優(yōu)勢(shì)
與 os.system 和 os.popen 相比,subprocess 提供了以下優(yōu)勢(shì):
更強(qiáng)大的功能: 支持雙向通信、管道、重定向等高級(jí)功能。
更好的資源管理: 可以自動(dòng)管理文件描述符和進(jìn)程,減少資源泄漏的風(fēng)險(xiǎn)。
更高的安全性: 通過(guò)列表形式傳遞命令和參數(shù),避免了命令注入的風(fēng)險(xiǎn)。
更豐富的返回信息: subprocess.run() 返回一個(gè) CompletedProcess 對(duì)象,包含退出碼、輸出和錯(cuò)誤等信息。
到此這篇關(guān)于Python 進(jìn)程調(diào)用(subprocess)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python 進(jìn)程調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python基于遞歸實(shí)現(xiàn)電話號(hào)碼映射功能示例
這篇文章主要介紹了Python基于遞歸實(shí)現(xiàn)電話號(hào)碼映射功能,結(jié)合實(shí)例形式分析了Python針對(duì)字典的遞歸、遍歷相關(guān)操作技巧,需要的朋友可以參考下2018-04-04
Python NumPy數(shù)組利器之np.zeros函數(shù)詳解與應(yīng)用實(shí)例
在Python的科學(xué)計(jì)算庫(kù)NumPy中,numpy.zeros()是一個(gè)非常重要的函數(shù),它用于創(chuàng)建一個(gè)指定形狀和數(shù)據(jù)類(lèi)型的全零數(shù)組,這篇文章主要給大家介紹了關(guān)于Python NumPy數(shù)組利器之np.zeros函數(shù)詳解與應(yīng)用實(shí)例的相關(guān)資料,需要的朋友可以參考下2024-06-06
python實(shí)現(xiàn)保存網(wǎng)頁(yè)到本地示例
這篇文章主要介紹了python實(shí)現(xiàn)保存網(wǎng)頁(yè)到本地示例,需要的朋友可以參考下2014-03-03
Tornado實(shí)現(xiàn)多進(jìn)程/多線程的HTTP服務(wù)詳解
這篇文章主要介紹了Tornado實(shí)現(xiàn)多進(jìn)程/多線程的HTTP服務(wù)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值2019-07-07
Python正則表達(dá)式re.compile()和re.findall()詳解
re?模塊提供了不少有用的函數(shù),用以匹配字符串,下面這篇文章主要給大家介紹了關(guān)于Python正則表達(dá)式re.compile()和re.findall()的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
Python使用Pexpect庫(kù)實(shí)現(xiàn)自動(dòng)化與終端交互的任務(wù)
Pexpect 是一個(gè) Python 庫(kù),用于自動(dòng)化與終端交互的任務(wù),它提供了一種簡(jiǎn)單的方式來(lái)編寫(xiě)腳本,以便與終端程序進(jìn)行交互,下面我們就來(lái)深入了解一下Pexpect庫(kù)的具體使用吧2023-12-12

