咱們常常須要經過Python去執行一條系統命令或腳本,系統的shell命令是獨立於你的python進程以外的,python
每執行一條命令,就是發起一個新進程,經過python調用系統命令或腳本的模塊在python2有os.system,linux
早期的Python版本中,咱們主要是經過os.system()、os.popen().read()等函數來執行命令行指令的,另外還有一個不多使用的commands模塊。shell
可是從Python 2.4開始官方文檔中建議使用的是subprocess模塊,因此os模塊和commands模塊的相關函數在這裏只提供一個簡單的使用示例,咱們重要要介紹的是subprocess模塊。windows
須要注意的是commands模塊不支持windows平臺,所以該實例是在Linux平臺下執行的函數
官方推出了subprocess,目地是提供統一的模塊來實現對系統命令或腳本的調用ui
三種執行命令的方法spa
subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs) #官方推薦命令行
subprocess.call(*popenargs, timeout=None, **kwargs) #跟上面實現的內容差很少,另外一種寫法3d
subprocess.Popen() #上面各類方法的底層封裝code
並鏈接到進程的輸入/輸出/錯誤輸出管道,並獲取進程的返回值。
In Windows , to use echo in subprocess, you would need to use shell=True .
This is because echo is not a separate executable, but rather a built-in command for the windows command line.
Example - process1 = subprocess.Popen(command1,stdout=subprocess.PIPE,shell=True)
參數說明: args: 要執行的shell命令,默認應該是一個字符串序列,如['df', '-Th']或('df', '-Th'),也能夠是一個字符串,如'df -Th',可是此時須要把shell參數的值置爲True。
window下執行shell=True加上 shell: 若是shell爲True,那麼指定的命令將經過shell執行。若是咱們須要訪問某些shell的特性,如管道、文件名通配符、環境變量擴展功能,這將是很是有用的。
固然,python自己也提供了許多相似shell的特性的實現,如glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser()和shutil等。
check: 若是check參數的值是True,且執行命令的進程以非0狀態碼退出,則會拋出一個CalledProcessError的異常,且該異常對象會包含 參數、退出狀態碼、以及stdout和stderr(若是它們有被捕獲的話)。
stdout, stderr: run()函數默認不會捕獲命令執行結果的正常輸出和錯誤輸出,若是咱們向獲取這些內容須要傳遞subprocess.PIPE,而後能夠經過返回的CompletedProcess類實例的stdout和stderr屬性或捕獲相應的內容; call()和check_call()函數返回的是命令執行的狀態碼,而不是CompletedProcess類實例,因此對於它們而言,stdout和stderr不適合賦值爲subprocess.PIPE; check_output()函數默認就會返回命令執行結果,因此不用設置stdout的值,若是咱們但願在結果中捕獲錯誤信息,能夠執行stderr=subprocess.STDOUT。
input: 該參數是傳遞給Popen.communicate(),一般該參數的值必須是一個字節序列,若是universal_newlines=True,則其值應該是一個字符串。
universal_newlines: 該參數影響的是輸入與輸出的數據格式,好比它的值默認爲False,此時stdout和stderr的輸出是字節序列;當該參數的值設置爲True時,stdout和stderr的輸出是字符串。
PIPE管道的意思,window下執行shell=True加上
print(subprocess.run(['dir'], shell = True, stdout = subprocess.PIPE))
標準寫法 subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True) 涉及到管道|的命令須要這樣寫 subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是這條命令直接交給系統去執行,不須要python負責解析
linux系統下執行:
#執行命令,返回命令執行狀態 , 0 or 非0 >>> retcode = subprocess.call(["ls", "-l"]) #執行命令,若是命令結果爲0,就正常返回,不然拋異常 >>> subprocess.check_call(["ls", "-l"]) 0 #接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果 >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #接收字符串格式命令,並返回結果 >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #執行命令,並返回結果,注意是返回結果,不是打印,下例結果返回給res >>> res=subprocess.check_output(['ls','-l']) >>> res b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'
經常使用參數:
下面這2條語句執行會有什麼區別?
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE) a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
區別是Popen會在發起命令後馬上返回,而不等命令執行結果。這樣的好處是什麼呢?
若是你調用的命令或腳本 須要執行10分鐘,你的主程序不需卡在這裏等10分鐘,能夠繼續往下走,幹別的事情,每過一會,經過一個什麼方法來檢測一下命令是否執行完成就行了。
Popen調用後會返回一個對象,能夠經過這個對象拿到命令執行結果或狀態等,該對象有如下方法 poll() Check if child process has terminated. Returns returncode wait() Wait for child process to terminate. Returns returncode attribute. terminate()終止所啓動的進程Terminate the process with SIGTERM kill() 殺死所啓動的進程 Kill the process with SIGKILL communicate()與啓動的進程交互,發送數據到stdin,並從stdout接收輸出,而後等待任務結束 >>> a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True) >>> a.communicate(b'22') (b'your guess:try bigger\n', b'')
send_signal(signal.xxx)
發送系統信號
pid
拿到所啓動進程的進程號