Hello,你們好,沉寂許久,我又來了,此次給你們分享的就是上述三個方法的使用範圍和區別,不熟悉的能夠在這個地方畫一個圓滿的句號了。javascript
os.system java
首先來看這個函數的文檔說明
python
是說是在一個子shell中執行命令, 也即至關於執行手動在CMD窗口輸入的命令
shell
import osprint(os.system('cd ..')) # 結果會打印出來0, 表示命令執行成功, 不然表示執行失敗,例如執行
print(os.system('mkdir new_folder')) # 執行第一次, 結果是0 第二次返回值是子目錄或者文件 new_folder已經存在,# 目前來講,我在使用的時候沒有出現太多的莫名其妙的錯誤,可是有大神說不建議用這個模塊,由下面兩種代替。
os.popen
windows
popen() 建立一個管道,經過fork一個子進程,而後該子進程執行命令。返回值在標準IO流中,該管道用於父子進程間通訊。父進程要麼從管道讀信息,要麼向管道寫信息,至因而讀仍是寫取決於父進程調用popen時傳遞的參數(w或r)其返回值是file read的對象, 對其進行讀取read()操做能夠看到執行的輸出緩存
import osprint(os.popen('mkdir new_folder').read()) # 建立成功的話沒有任何返回值, 可是若是已經存在的話, 子目錄或者文件 new_folder已經存在,print(os.popen('ipconfig').read()) # 跟在cmd 窗口敲該命令結果同樣, 顯示該計算機的ip詳情信息 不添加read的話, <os._wrap_close object at 0x0000022554EBCFD0>
subprocess.Popen
bash
該模塊是在2.4版本中新增的,官方文檔描述能夠用來替換如下函數:os.system、os.spawn、os.popen、popen2,它的目的是啓動一個新進程而且與之進行通訊,最經常使用的定義是使用類Popen(), 它能夠建立進程,而且與進程進行復雜的交互,一個比較明顯的缺點是它是一個阻塞的方法,若是運行的CMD命令時產生的內容很是多,函數就是會很是容易阻塞,另一點,它也不會打印出CMD的執行信息微信
import subprocesssubprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)# 其中args值的是須要傳入的要執行的程序路徑(字符串),若是是列表的話,第一項是程序的路徑,後面的參數是執行該程序所須要的參數,這個與popen一致。
# 下面是各個參數的詳解# bufsize 指定緩衝,0 無緩衝, 1 行緩衝 其餘正值 緩衝區大小 負值 採用的默認系統緩衝(通常是全緩衝)# executable: 用於指定可執行程序。通常狀況下咱們經過args參數來設置所要運行的程序。若是將參數shell設爲 True,executable將指定程序使用的shell。在windows平臺下,默認的shell由COMSPEC環境變量來指定。# stdin stdout stderr 三者是成程序的標準輸入、標準輸出、錯誤句柄。能夠賦值爲None(沒有任何重定向,繼承父進程)、PIPE(建立管道)、文件對象、文件描述符(整數)等,其中stderr仍是能夠設置成STDOUT,# preexc_fn:只是在Unix下生效,用於指定一個可執行對象,它將在子進程運行以前被調用。# close_sfs:在windows平臺下,若是若是該參數被設置成True,那麼新建立的子進程將不會繼承父進程的輸入輸出錯誤管道,咱們不能將該函數設置爲True同時重定向子進程的標準輸入輸出與錯誤。# shell:在unix下就是至關於在args前面添加了"/bin/sh /c" 在windows下至關於添加了"cmd.exe /c"# cmd:設置子進程的工做目錄# env:字典類型,用於指定子進程的環境變量,若是env=None,那麼子進程的環境變量將從父進程中繼承# Universal_newlines:不一樣操做系統下,文本的換行符是不同的。如:windows下用'/r/n'表示換,而Linux下用 '/n'。若是將此參數設置爲True,Python統一把這些換行符看成’/n’來處理。# 參數startupinfo與createionflags只在windows下有效,它們將被傳遞給底層的CreateProcess()函數,用 於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等。
下面解釋一下緩衝區
函數
概念:它的本質是一塊存儲區域。ui
爲何要產生?
這就涉及到了CPU與硬件通訊問題,咱們都知道,CPU的處理速度是很快的,可是存儲設備以及其餘的I/O(鍵盤輸入文字)操做倒是很慢的,因此爲了保證CPU與低速部件通訊吻合住,就須要先將CPU的處理結果的輸出暫時存儲到某處,當達到某個閾值的時候,再去調用CPU進行統一處理,這樣就會讓CPU變得高效起來,由於咱們的文字輸入以及存儲到硬盤對於CPU來講是很慢的,CPU不能總是等着咱們,所以引入緩衝區
緩衝區的分類:
能夠分爲全緩衝、行緩衝以及無緩衝全緩衝:緩存在緩衝區的內容快要達到緩衝區容量上限的時候。纔去寫入磁盤或者調用fflush才能寫入到磁盤,那麼對於緩衝區沒滿或者沒有手動刷新緩存,緩衝區的內容是不會寫入到磁盤的。行緩衝:咱們的標準輸入、輸出都是採用的行緩存,也即遇到換行符的時候,纔會將緩存區的東西寫入到磁盤。無緩衝:有的時候,但願一些內容在第一時間寫入磁盤或者顯示出來,好比顯示錯誤信息的時候,典型的例子就是標準出錯信息,它就是直接顯示出錯信息, 而不會先放入緩存。
須要知道的是,在緩衝區滿了、程序結束的時候、手動調用fflush的時候,緩衝區纔會獲得刷新而且寫入到磁盤。
因此總的來講,最後一個能夠說能替代前兩項的,
os.system能夠用subprocess.call來替代,os.popen可使用subprocess。Popen來替代。
附一段代碼,使用subprocess從運行的子進程中實時獲取輸出
首先是模擬標準輸出和標準錯誤輸出的子程序 sub_process.py
import sysimport time
for i in range(5): sys.stdout.write('Processing {}\n'.format(i)) time.sleep(1)
for i in range(5): sys.stderr.write('Error {}\n'.format(i)) time.sleep(1)
接着是驅動子程序的主程序 main_process.py
import shleximport subprocess
if __name__ == '__main__': shell_cmd = 'python sub_process.py' cmd = shlex.split(shell_cmd) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while p.poll() is None: line = p.stdout.readline() line = line.strip() if line: print('Subprogram output: [{}]'.format(line)) if p.returncode == 0: print('Subprogram success') else: print('Subprogram failed')
經過指定stderr=subprocess.STDOUT,將標準錯誤重定向到標準輸出,期待的結果是每隔一秒得到一條信息,可是實際上確實間隔了10秒一次性輸出了出來,這就是緩衝區的概念,它不會當即輸出,會作緩存,知道緩存滿或者手動刷新或者函數執行結束纔會輸出,想要看到實時輸出的效果須要手動刷新,即
import sysimport time
for i in range(5): sys.stdout.write('Processing {}\n'.format(i)) sys.stdout.flush() time.sleep(1)
for i in range(5): sys.stderr.write('Error {}\n'.format(i)) sys.stderr.flush() time.sleep(1)
再去執行主進程函數就會出現預期的效果。
本文分享自微信公衆號 - IT民工技術之路(python_er)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。