淺談Python調用Shell腳本的三種常用方式
一、通過 Python 來調用 Shell 腳本的三種常用方式
三種方式的優(yōu)缺點
| os.system | subprocess.run | subprocess.Popen | |
|---|---|---|---|
| 是否需要解析參數 | no | yes | yes |
| 同步執(zhí)行(等待Shell執(zhí)行結果) | yes | yes | no |
| 能夠獲得 shell 的輸入和輸出 | no | yes | yes |
| Shell 執(zhí)行結果返回值 | return value | object | object |
os.system
import os
return_code=os.system('ls -al .')
print(return_code)
/home/topeet/miniconda3/envs/rknn/bin/python3 /home/topeet/test/python/test.py
總用量 20
drwxrwxr-x 3 topeet topeet 4096 8月 11 00:56 .
drwxrwxr-x 6 topeet topeet 4096 7月 27 06:27 …
drwxrwxr-x 3 topeet topeet 4096 8月 11 00:36 .idea
-rw-rw-r-- 1 topeet topeet 504 7月 27 07:35 main.py
-rwxrwxr-x 1 topeet topeet 2442 8月 11 00:56 test.py
0
也會將Shell語句的輸出輸出到的 Python的命令控制臺中。
但是 Python 的能夠獲取的返回值,是數字,0 代表 Shell 語句/腳本的執(zhí)行成功,否則表示Shell執(zhí)行的狀態(tài)值。
適用于不需要詳細的返回信息的 shell 腳本
傳入 Shell 命令的參數,都是完整的 String。
subprocess.run(推薦)
1 、 能夠相當方便的控制 shell 命令的輸入和輸出
- 1 傳入的參數是一個 數組 而不是字符串。
import subprocess return_code=subprocess.run(['ls','-al','.']) print(return_code)
/home/topeet/miniconda3/envs/rknn/bin/python3 /home/topeet/test/python/test.py
總用量 20
drwxrwxr-x 3 topeet topeet 4096 8月 11 01:00 .
drwxrwxr-x 6 topeet topeet 4096 7月 27 06:27 …
drwxrwxr-x 3 topeet topeet 4096 8月 11 00:36 .idea
-rw-rw-r-- 1 topeet topeet 504 7月 27 07:35 main.py
-rwxrwxr-x 1 topeet topeet 2533 8月 11 01:00 test.py
CompletedProcess(args=['ls', '-al', '.'], returncode=0)
- 2 執(zhí)行返回的結果是一個CompletedProcess對象
2 、忽略shell 腳本執(zhí)行的結果
import subprocess return_code=subprocess.run(['ls','-al','.'],stdout=subprocess.DEVNULL) print(return_code)
(base) topeet@ubuntu:~/test/python$ python test.py
CompletedProcess(args=['ls', '-al', '.'], returncode=0)
- 2 輸出結果就僅有 Python 程序運行出的結果。
3 、指定 shell 命令的輸入參數(通過 input 參數來傳入)
import subprocess useless_cat_call=subprocess.run(['cat'],stdout=subprocess.PIPE,text=True,input="Hello") print(useless_cat_call.stdout)
/home/topeet/miniconda3/envs/rknn/bin/python3 /home/topeet/test/python/test.py
Hello
- stdout=subprocess.PIPE 告訴 Python,重定向 Shell 命令的輸出,并且這部分輸出可以被后面的 Python 程序所調用。
- text=True 告訴 Python,將 shell 命令的執(zhí)行的 stdout 和 stderr 當成字符串. 默認是當成 bytes.
- input="Hello from the other side" 告訴 Python,shell 命令的輸入參數.
4 、開啟 shell 命令的執(zhí)行校驗
- 1 當 shell 的執(zhí)行出現任何問題,都會拋出一個異常。
import subprocess
failed_command=subprocess.run(['false'],text=True)
print("The exit code was: %d" % failed_command.returncode)
/home/topeet/miniconda3/envs/rknn/bin/python3 /home/topeet/test/python/test.py
The exit code was:1
5、subprocess.run方法參數的介紹
核心控制參數??
- ??args??
- ??作用??:指定要執(zhí)行的命令,支持??列表??(推薦)或??字符串??形式。
- ??注意??:列表形式可避免命令注入風險;字符串形式必須設置 shell=True。
subprocess.run(["ls", "-l"]) # 安全方式(列表)[1,3]
subprocess.run("ls -l", shell=True) # 字符串需配合 shell=True[5]
- ??shell??
- ??作用??:是否通過系統(tǒng) Shell(如 /bin/sh或 cmd.exe)執(zhí)行命令。
- ??風險??:shell=True可能引發(fā)安全漏洞(如執(zhí)行惡意輸入),非必要不啟用
- ??適用場景??:需 Shell 特性(如通配符 *、管道 |)時使用。
- ??timeout??
- ??作用??:設置命令超時時間(秒),超時拋出 TimeoutExpired異常。
- ??示例??:
try:
subprocess.run(["sleep", "10"], timeout=5)
except TimeoutExpired:
print("命令超時!") # 5秒后中斷[3,6]
輸入/輸出處理參數??
- ??stdin、stdout、stderr??
- ??作用??:控制子進程的標準流,可選值:
- subprocess.PIPE:捕獲數據流(通過 result.stdout訪問)
- subprocess.DEVNULL:丟棄輸出(類似 /dev/null)。
- 文件對象:重定向到文件。
- ??示例??:
result = subprocess.run(["ls"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- ??capture_output??
- ??作用??:簡化輸出捕獲(等價于設置 stdout=PIPE, stderr=PIPE)。
- ??沖突??:不可與 stdout/stderr同時使用
- ??input??
- ??作用??:向子進程的 stdin 傳遞數據,需配合 stdin=PIPE(自動啟用)。
- ??數據類型??:
- text=True時:??字符串??(如 input="Hello")
- 默認:??字節(jié)流??(如 input=b"Hello")。
- ??text/ encoding??
- ??作用??:控制輸入/輸出的文本模式:
- text=True:輸入/輸出自動轉為字符串(等價于 universal_newlines=True)
- encoding="utf-8":指定編解碼方式(如處理中文)。
執(zhí)行環(huán)境參數??
- ??cwd??
- ??作用??:設置子進程的工作目錄。
- ??示例??:
subprocess.run(["pwd"], cwd="/tmp") # 輸出 "/tmp
- ??env??
- ??作用??:自定義環(huán)境變量(字典形式),默認繼承父進程環(huán)境。
- ??示例??:
env = {"PATH": "/usr/bin", "MY_VAR": "test"}
subprocess.run(["echo", "$MY_VAR"], env=env, shell=True)[4](@ref)
異常與狀態(tài)處理??
- ??check??
- ??作用??:若子進程返回??非零退出碼??,拋出 CalledProcessError異常。
- ??示例??:
try:
subprocess.run(["false"], check=True) # 總是失敗的命令
except CalledProcessError as e:
print(f"錯誤碼: {e.returncode}, 錯誤: {e.stderr}")
- ??返回值 CompletedProcess??
- ??屬性??:
- returncode:退出狀態(tài)碼(0 表示成功)。
- stdout/stderr:捕獲的輸出(文本或字節(jié)流)。
- args:執(zhí)行的命令
- ??方法??:
- check_returncode():非零退出碼時拋出異常。
最佳實踐總結??
- ??安全優(yōu)先??:
- 使用??列表??傳參(如 ["ls", "-l"]),避免 shell=True除非必要
- ??輸出處理??:
- 需捕獲輸出時,用 capture_output=True+ text=True簡化代碼。
- ??異常管理??:
- 關鍵命令添加 check=True+ try/except確保失敗可追溯
- ??跨平臺注意??:
- Windows 部分命令(如 dir)需 shell=True
- ??性能優(yōu)化??:
- 避免頻繁調用高開銷命令(如反復啟動 Shell)
subprocess.Popen
1 、subprocess.Popen能夠提供更大的靈活性。
subprocess.run 可以看成是 subprocess.Popen 一個簡化抽象。
2 、subprocess.Popen的使用與注意
1.默認情況下, subprocess.Popen 不會中暫停 Python 程序本身的運行(異步)
2.但是如果你非得同前面兩種方式一樣,同步運行,你可以加上 .wait() 方法。
3.當我們仍然處在異步的狀況,通過 poll() 來輪詢,知道shell 命令是否運行結束與否?當放回結果為 None,則表示程序還在運行,否者會返回一個狀態(tài)碼。
如果想, 指定輸入參數 ,則需要通過 communicate() 方法。
import subprocess useless_cat_call=subprocess.Popen(['cat'],stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE,text=True) output,errors=useless_cat_call.communicate(input="hello") useless_cat_call.wait() print(output) print(errors)
/home/topeet/miniconda3/envs/rknn/bin/python3 /home/topeet/test/python/test.py
hello
到此這篇關于淺談Python調用Shell腳本的三種常用方式的文章就介紹到這了,更多相關Python調用Shell腳本內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用python將CSV和Excel表格數據導入到Word表格
在不同格式的文檔之間進行數據傳輸是非常重要的操作,例如將CSV和Excel表格數據導入到Word文檔中,不僅可以實現數據的有效整合與展示,還能極大地提升工作效率和文檔的專業(yè)性,本文將介紹如何使用Python將CSV和Excel表格數據導入到Word文檔中并創(chuàng)建表格2024-09-09
Python爬蟲庫BeautifulSoup的介紹與簡單使用實例
BeautifulSoup是一個可以從HTML或XML文件中提取數據的Python庫,本文為大家介紹下Python爬蟲庫BeautifulSoup的介紹與簡單使用實例其中包括了,BeautifulSoup解析HTML,BeautifulSoup獲取內容,BeautifulSoup節(jié)點操作,BeautifulSoup獲取CSS屬性等實例2020-01-01

