哈嘍大家好,我是鹹魚
我們知道,python 在自動化領域中被廣泛應用,可以很好地自動化處理一些任務
就比如編寫 Python 指令碼自動化執行重複性的任務,如檔案處理、資料處理、系統管理等需要執行其他程式或者與作業系統互動的任務
那麼今天我們來看一下在 python 中如何執行 shell 命令來與作業系統互動
一般來講,最好是用 python 自帶的函數或模組,而不是直接呼叫其他程式或者作業系統的命令
我們來看一下 python 中有哪些自帶模組或者方法可以實現
pathlib
模組
如果你需要建立或者刪除檔案/目錄,檢查檔案是否存在或者改變許可權等,你完全不需要使用作業系統的命令
你可以完全通過 pathlib
模組來實現,它有你需要的一切,甚至 glob
、os.path
都可以不用
我們來簡單看一下關於這個模組的例子
from pathlib import Path
# 建立一個Path物件表示當前工作目錄
current_directory = Path.cwd()
print("當前工作目錄:", current_directory)
# 建立一個新的目錄
new_directory = current_directory / "my_folder"
new_directory.mkdir()
print("建立新目錄:", new_directory)
# 建立一個新的檔案
new_file = new_directory / "my_file.txt"
new_file.touch()
print("建立新檔案:", new_file)
# 寫入檔案
with new_file.open(mode='w') as f:
f.write("Hello, World!")
# 讀取檔案內容
with new_file.open() as f:
content = f.read()
print("檔案內容:", content)
# 遍歷目錄中的檔案
for file in new_directory.iterdir():
print("檔案:", file)
# 刪除檔案和目錄
new_file.unlink()
new_directory.rmdir()
print("刪除檔案和目錄:", new_file, new_directory)
tempfile
模組
在 Python 中臨時建立和處理檔案時,tempfile
模組提供了方便的方法
它可以在臨時目錄中建立臨時檔案和臨時資料夾,並提供了一些便利的函數和類來管理這些臨時檔案
import tempfile
# 建立臨時檔案
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.write(b'This is a temporary file.')
temp_file.close()
# 列印臨時檔案路徑
print("臨時檔案路徑:", temp_file.name)
# 開啟臨時檔案並讀取內容
with open(temp_file.name, 'r') as f:
content = f.read()
print("臨時檔案內容:", content)
# 建立臨時目錄
temp_dir = tempfile.TemporaryDirectory()
# 列印臨時目錄路徑
print("臨時目錄路徑:", temp_dir.name)
# 自動清理臨時目錄
temp_dir.cleanup()
shutil
模組
前面我們知道 pathlib
模組滿足了 python 中大多數與檔案相關的需求
如果需要例如複製,移動,刪除或建立檔案,可以使用 shutil
模組
import shutil
# 複製檔案
shutil.copy('source_file.txt', 'destination_folder/')
# 移動檔案
shutil.move('source_file.txt', 'destination_folder/')
# 刪除檔案
shutil.remove('file_to_be_deleted.txt')
# 刪除目錄
shutil.rmtree('directory_to_be_deleted/')
# 建立壓縮檔案
shutil.make_archive('archive', 'zip', 'source_folder/')
# 解壓縮檔案
shutil.unpack_archive('archive.zip', 'destination_folder/')
os
模組
os
模組是 Python 中一個更老的、更底層的模組,提供了與作業系統互動和執行檔案系統操作的功能
但是隨著 python 的發展,越來越多物件導向的、更直觀和易於使用的模組可以供大家使用
對於 os
模組,大家可以瞭解一下就行了
import os
print(os.getenv('PATH'))
# 獲取環境變數PATH的值,並列印
# 範例輸出:/home/martin/.local/bin:/usr/local/sbin:/usr/local/bin:...
print(os.uname())
# 獲取作業系統的資訊,並列印
# 範例輸出:posix.uname_result(sysname='Linux', nodename='...', release='...', version='...', machine='x86_64')
print(os.times())
# 獲取程序的CPU時間資訊,並列印
# 範例輸出:posix.times_result(user=0.01, system=0.0, children_user=0.0, children_system=0.0, elapsed=1740.63)
print(os.cpu_count())
# 獲取可用的CPU核心數量,並列印
# 範例輸出:16
print(os.getloadavg())
# 獲取系統的平均負載,並列印
# 範例輸出:(2.021484375, 2.35595703125, 2.04052734375)
old_umask = os.umask(0o022)
# 設定檔案建立時的許可權掩碼,並將舊的掩碼儲存起來
# 在此處可以執行與檔案相關的操作...
os.umask(old_umask)
# 恢復舊的檔案許可權掩碼
sh
模組
sh
模組不是 python 的標準模組,它是一個第三方模組,在使用之前我們需要安裝它
pip install sh
import sh
# 在 $PATH 中執行任何命令...
print(sh.ls('-la'))
# 執行ls命令並列印輸出
# 範例輸出:
# total 36
# drwxrwxr-x 2 martin martin 4096 apr 8 14:18 .
# drwxrwxr-x 41 martin martin 20480 apr 7 15:23 ..
# -rw-rw-r-- 1 martin martin 30 apr 8 14:18 examples.py
ls_cmd = sh.Command('ls')
print(ls_cmd('-la')) # 顯式呼叫
# 使用Command物件執行ls命令並列印輸出
# 範例輸出與上述相同
# 如果命令不在PATH中:
custom_cmd = sh.Command('/path/to/my/cmd')
custom_cmd('some', 'args') # 執行自定義命令並傳遞引數
with sh.contrib.sudo:
# 使用'sudo'執行一些操作...
...
# 使用'sudo'執行一些操作的上下文環境
當我們通過 sh
模組去執行一些 shell 命令時,sh 模組會嘗試在本地環境變數($PATH)中查詢帶有該名稱的內建 shell 命令或二進位制檔案
如果沒有找到,可以自己新增命令路徑
custom_cmd = sh.Command('/path/to/my/cmd')
custom_cmd('some', 'args') # 執行自定義命令並傳遞引數
如果要將命令的輸出寫入到檔案裡面,可以使用 _out
引數
#相當於 ip address > /tmp/ipaddr
sh.ip.address(_out='/tmp/ipaddr')
我們在敲 shell 命令時通常會使用到管道符(|),在 sh 模組中通過 _in
引數來實現
print(sh.awk('{print $9}', _in=sh.ls('-la')))
# 等同於 "ls -la | awk '{print $9}'"
print(sh.wc('-l', _in=sh.ls('.', '-1')))
# 等同於 "ls -1 | wc -l"
對於例外處理,我們可以簡單地處理 ErrorReturnCode
或 TimeoutException
異常
try:
sh.cat('/tmp/doesnt/exist')
except sh.ErrorReturnCode as e:
print(f'Command {e.full_cmd} exited with {e.exit_code}')
# '/usr/bin/cat /tmp/doesnt/exist' 命令結果返回 1
curl = sh.curl('https://httpbin.org/delay/5', _bg=True)
try:
curl.wait(timeout=3)
except sh.TimeoutException:
print("Command timed out...")
curl.kill()