這裏主要總結下,在 Python 代碼腳本里,涉及到調用 Shell 腳本、終端命令行、其它 Python 腳本的場景.
1. 方法1 - os.system()
os.system() - 只返回狀態碼,執行結果會輸出到stdout,即輸出到終端. 僅在 Linux 中有效.
用法:
import os
# 不傳遞參數
os.system(cmd) # cmd 即爲Linux 終端命令行指令
# 返回命令執行的狀態值
# 輸出數字爲 0,表示正確執行;
# 輸出數字非 0,表示錯誤執行
# 傳遞一個參數
os.system("shell command argus %s" % argus1)
# 傳遞兩個及以上參數
os.system("shell command argus %s %s" % (argus1, argus2)
如:
import os
# 不傳遞參數
os.system("ls") # 顯示文件夾文件,不包含隱藏文件
os.system("ls -a") # 顯示文件夾所有文件,包含隱藏文件
os.system("pwd") # 獲取當前目錄
os.system("top") # 顯示進程情況,退出需要輸入 'q'.
# 傳遞一個參數
os.system("python test.py -i %s" %inputparam)
# 傳遞兩個及以上參數
os.system("python test.py -i %s -b %s" % (inputparam1, inputparam2))
注:os.system(cmd)
不能執行交互式命令,如 ssh root@ip
需要輸入密碼的終端命令.
Python 字符格式化:
%s 字符串 (採用str()的顯示)
%r 字符串 (採用repr()的顯示)
%c 單個字符
%b 二進制整數
%d 十進制整數
%i 十進制整數
%o 八進制整數
%x 十六進制整數
%e 指數(基底寫爲e)
%E 指數(基底寫爲E)
%f 浮點數
%F 浮點數,與上相同
%g 指數(e)或浮點數 (根據顯示長度)
%G 指數(E)或浮點數 (根據顯示長度)
%% 字符"%"
2. 方法二 - os.popen()
os.popen() - 用於從一個命令打開一個管道,返回結果是一個連接管道的文件對象,該文件對象的操作方法同 open(),可以從該文件對象中讀取返回結果. 如果執行成功,不會返回狀態碼,如果執行失敗,則會將錯誤信息輸出到stdout,並返回一個空字符串. 在Unix,Windows中有效.
用法:
import os
os.popen(cmd, mode, bufsize)
# cmd - 使用的命令。
# mode - 模式權限可以是 'r'(默認) 或 'w'.
# bufsize - 指明文件需要的緩衝大小:
# 0-無緩衝;1-行緩衝;
# 其它正值表示使用參數大小的緩衝(大概值,以字節爲單位)
# 負的bufsize意味着使用系統的默認值.
# 一般來說,對於tty設備,它是行緩衝;
# 對於其它文件,它是全緩衝. 如果沒有改參數,使用系統的默認值.
# 返回一個文件描述符號爲 fd 的打開的文件對象.
如:
import os
files = os.popen("ls").readlines() # 文件夾內所有文件的列表.
注: os.popen()
在大多數場景都是挺好用,但需要注意:
[1] - 在需要讀取命令執行結果時,避免在命令無法退出或進入交互模式的場景應用 os.popen()
;
[2] - os.popen()
無法滿足需求時,可以考慮subprocess.Popen()
.
3. 方法三 - subprocess 模塊
subprocess 模塊是 Python 2.4 版本開始引入的模塊,主要用來取代 一些舊的模塊方法,如os.system
、os.spawn
、os.popen
、commands.*
等.
subprocess 通過子進程來執行外部指令,並通過 input/output/error 管道,獲取子進程的執行的返回信息.
3.1. subprocess.Popen()
用法:
class subprocess.Popen(args,
bufsize=-1,
executable=None,
stdin=None,
stdout=None,
stderr=None,
preexec_fn=None,
close_fds=True,
shell=False,
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0,
restore_signals=True,
start_new_session=False,
pass_fds=(),
*,
encoding=None,
errors=None)
參數說明:
[1] - args 參數: 要執行的命令或可執行文件的路徑. 一個由字符串組成的序列(通常是列表),列表的第一個元素是可執行程序的路徑,剩下的是傳給這個程序的參數,如果沒有要傳給這個程序的參數,args 參數可以僅僅是一個字符串。
[2] - bufsize:控制 stdin, stdout, stderr 等參數指定的文件的緩衝,和打開文件的 open()
函數中的參數 bufsize 含義相同.
[3] - executable:如果這個參數不是 None,將替代參數 args 作爲可執行程序;
[4] - stdin:指定子進程的標準輸入;
[5] - stdout:指定子進程的標準輸出;
[6] - stderr:指定子進程的標準錯誤輸出;
對於 stdin, stdout 和 stderr 而言,如果它們是 None(默認情況),那麼子進程使用和父進程相同的標準流文件. 父進程如果想要和子進程通過 communicate() 方法通信,對應的參數必須是 subprocess.PIPE;stdin, stdout 和 stderr 也可以是已經打開的 file 對象,前提是以合理的方式打開,比如 stdin 對應的文件必須要可讀等.
[7] - preexec_fn:默認是None,否則必須是一個函數或者可調用對象,在子進程中首先執行這個函數,然後再去執行爲子進程指定的程序或Shell.
[8] - close_fds:布爾型變量,爲 True 時,在子進程執行前強制關閉所有除 stdin,stdout和stderr外的文件;
[9] - shell:布爾型變量,明確要求使用shell運行程序,與參數 executable 一同指定子進程運行在什麼 Shell 中 —— 如果executable=None 而 shell=True,則使用 /bin/sh 來執行 args 指定的程序;也就是說,Python首先起一個shell,再用這個shell來解釋指定運行的命令.
[10] - cwd:代表路徑的字符串,指定子進程運行的工作目錄,要求這個目錄必須存在;
[11] - env:字典,鍵和值都是爲子進程定義環境變量的字符串;
[12] - universal_newline:布爾型變量,爲 True 時,stdout 和 stderr 以通用換行(universal newline)模式打開,
[13] - startupinfo:見下一個參數;
[14] - creationfalgs:最後這兩個參數是Windows中才有的參數,傳遞給Win32的CreateProcess API調用.
例1:
import subprocess
p = subprocess.Popen('ls -l', shell=True)
p.returncode
p.wait() # 0
p.pid # 子進程的 PID
p.returncode # 子進程的返回狀態.
# None —— 子進程尚未結束;
# ==0 —— 子進程正常退出;
# > 0—— 子進程異常退出,returncode對應於出錯碼;
# < 0—— 子進程被信號殺掉了.
p.stdin
p.stdout
p.stderr
例2:
import sbuprocess
proc = subprocess.Popen(cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
while True:
buff = proc.stdout.readline()
print(buff)
if buff == '' and proc.poll() != None:
break
else:
.....
except Exception:
data["status"] = -1
finally:
return data
From: python的subprocess模塊
subprocess.Popen() - 在一些複雜場景中,需要將一個進程的執行輸出作爲另一個進程的輸入. 在另一些場景中,需要先進入到某個輸入環境,然後再執行一系列的指令等. 這個時候就需要使用到suprocess.Popen()方法,該方法有以下參數:
[1] - args:shell命令,可以是字符串,或者序列類型,如list,tuple.
[2] - bufsize:緩衝區大小,可不用關心
[3] - stdin, stdout, stderr:分別表示程序的標準輸入,標準輸出及標準錯誤
[4] - shell: 與 subprocess.call() 中相同.
[5] - cwd:用於設置子進程的當前目錄
[6] - env:用於指定子進程的環境變量. 如果env=None,則默認從父進程繼承環境變量.
[7] - universal_newlines:不同系統的的換行符不同,當該參數設定爲true時,則表示使用n作爲換行符.
例如1:
status = subprocess.Popen('mkdir subprocesstest',shell=True,cwd='/root')
例如2:
import subprocess
obj = subprocess.Popen(["python"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
obj.stdin.write('print 1 \n')
obj.stdin.write('print 2 \n')
obj.stdin.write('print 3 \n')
obj.stdin.write('print 4 \n')
obj.stdin.close()
cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_error = obj.stderr.read()
obj.stderr.close()
print cmd_out
print cmd_error
# 或
import subprocess
obj = subprocess.Popen(["python"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
obj.stdin.write('print 1 \n')
obj.stdin.write('print 2 \n')
obj.stdin.write('print 3 \n')
obj.stdin.write('print 4 \n')
out_error_list = obj.communicate()
print out_error_list
例如3:
import subprocess
# 將一個子進程的輸出,作爲另一個子進程的輸入:
child1 = subprocess.Popen(["cat","/etc/passwd"],
stdout=subprocess.PIPE)
child2 = subprocess.Popen(["grep","0:0"],
stdin=child1.stdout,
stdout=subprocess.PIPE)
out = child2.communicate()
例如4:
import subprocess
child = subprocess.Popen('sleep 60',
shell=True,
stdout=subprocess.PIPE)
child.poll() # 檢查子進程狀態
child.kill() # 終止子進程
child.send_signal() # 向子進程發送信號
child.terminate() # 終止子進程
3.2. subprocess.call()
subprocess.call() - 執行命令,並返回執行狀態. 其中shell參數爲False時,命令需要通過列表的方式傳入;當shell爲True時,可直接傳入命令.
例如:
import subprocess
status1 = subprocess.call(['df','-hT'],shell=False)
status2 = subprocess.call('df -hT', shell=True)
print(status1) # 0
print(status2) # 0
3.3. subprocess.check_call()
subprocess.check_call() - 用法與subprocess.call()類似,區別是,當返回值不爲0時,直接拋出異常.
例如:
import subprocess
status2 = subprocess.check_call('df -hT', shell=True)
print(status2) # 0
status1 = subprocess.check_call('dfdadas', shell=True) #出錯,異常.
3.4. subprocess.check_output()
subprocess.check_output() - 用法與subprocess.call()、subprocess.check_call()類似,區別是,××如果當返回值爲0時,直接返回輸出結果,如果返回值不爲0,直接拋出異常**.
subprocess.check_output() 僅在python3.x中才有.