Python中subprocess學習
subprocess的目的就是啟動一個新的程式並且與之通訊。
subprocess模組中只定義了一個類: Popen。可以使用Popen來建立程式,並與程式進行復雜的互動。它的建構函式如下:
subprocess.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可以是字串或者序列型別(如:list,元組),用於指定程式的可執行檔案及其引數。如果是序列型別,第一個元素通常是可執行檔案的路徑。我們也可以顯式的使用executeable引數來指定可執行檔案的路徑。
引數stdin, stdout, stderr分別表示程式的標準輸入、輸出、錯誤控制程式碼。他們可以是PIPE,檔案描述符或檔案物件,也可以設定為None,表示從父程式繼承。
如果引數shell設為true,程式將通過shell來執行。
引數env是字典型別,用於指定子程式的環境變數。如果env = None,子程式的環境變數將從父程式中繼承。
subprocess.PIPE
在建立Popen物件時,subprocess.PIPE可以初始化stdin, stdout或stderr引數。表示與子程式通訊的標準流。
subprocess.STDOUT
建立Popen物件時,用於初始化stderr引數,表示將錯誤通過標準輸出流輸出。
Popen的方法:
Popen.poll()
用於檢查子程式是否已經結束。設定並返回returncode屬性。
Popen.wait()
等待子程式結束。設定並返回returncode屬性。
Popen.communicate(input=None)
與子程式進行互動。向stdin傳送資料,或從stdout和stderr中讀取資料。可選引數input指定傳送到子程式的引數。Communicate()返回一個元組:(stdoutdata, stderrdata)。注意:如果希望通過程式的stdin向其傳送資料,在建立Popen物件的時候,引數stdin必須被設定為PIPE。同樣,如果希望從stdout和stderr獲取資料,必須將stdout和stderr設定為PIPE。
Popen.send_signal(signal)
向子程式傳送訊號。
Popen.terminate()
停止(stop)子程式。在windows平臺下,該方法將呼叫Windows API TerminateProcess()來結束子程式。
Popen.kill()
殺死子程式。
Popen.stdin,Popen.stdout ,Popen.stderr ,官方文件上這麼說:
stdin, stdout and stderr specify the executed programs’ standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None.
Popen.pid
獲取子程式的程式ID。
Popen.returncode
獲取程式的返回值。如果程式還沒有結束,返回None。
---------------------------------------------------------------
簡單的用法:
p=subprocess.Popen("dir", shell=True)
p.wait()
shell引數根據你要執行的命令的情況來決定,上面是dir命令,就一定要shell=True了,p.wait()可以得到命令的返回值。
如果上面寫成a=p.wait(),a就是returncode。那麼輸出a的話,有可能就是0【表示執行成功】。
---------------------------------------------------------------------------
程式通訊
如果想得到程式的輸出,管道是個很方便的方法,這樣:
p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdoutput,erroutput) = p.<span>commu</span>nicate()
p.communicate會一直等到程式退出,並將標準輸出和標準錯誤輸出返回,這樣就可以得到子程式的輸出了。
再看一個communicate的例子。
上面的例子通過communicate給stdin傳送資料,然後使用一個tuple接收命令的執行結果。
------------------------------------------------------------------------
上面,標準輸出和標準錯誤輸出是分開的,也可以合併起來,只需要將stderr引數設定為subprocess.STDOUT就可以了,這樣子:
- p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (stdoutput,erroutput) = p.<span>commu</span>nicate()
p=subprocess.Popen("dir", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while True:
buff = p.stdout.readline()
if buff == '' and p.poll() != None:
break
------------------------------------------------------
死鎖
但是如果你使用了管道,而又不去處理管道的輸出,那麼小心點,如果子程式輸出資料過多,死鎖就會發生了,比如下面的用法:
p=subprocess.Popen("longprint", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p.wait()
longprint是一個假想的有大量輸出的程式,那麼在我的xp, Python2.5的環境下,當輸出達到4096時,死鎖就發生了。當然,如果我們用p.stdout.readline或者p.communicate去清理輸出,那麼無論輸出多少,死鎖都是不會發生的。或者我們不使用管道,比如不做重定向,或者重定向到檔案,也都是可以避免死鎖的。
----------------------------------
subprocess還可以連線起來多個命令來執行。
在shell中我們知道,想要連線多個命令可以使用管道。
在subprocess中,可以使用上一個命令執行的輸出結果作為下一次執行的輸入。例子如下:
例子中,p2使用了第一次執行命令的結果p1的stdout作為輸入資料,然後執行tail命令。
- -------------------
下面是一個更大的例子。用來ping一系列的ip地址,並輸出是否這些地址的主機是alive的。程式碼參考了python unix linux 系統管理指南。
#!/usr/bin/env python
from threading import Thread
import subprocess
from Queue import Queue
num_threads=3
ips=['127.0.0.1','116.56.148.187']
q=Queue()
def pingme(i,queue):
while True:
ip=queue.get()
print 'Thread %s pinging %s' %(i,ip)
ret=subprocess.call('ping -c 1 %s' % ip,shell=True,stdout=open('/dev/null','w'),stderr=subprocess.STDOUT)
if ret==0:
print '%s is alive!' %ip
elif ret==1:
print '%s is down...'%ip
queue.task_done()
#start num_threads threads
for i in range(num_threads):
t=Thread(target=pingme,args=(i,q))
t.setDaemon(True)
t.start()
for ip in ips:
q.put(ip)
print 'main thread waiting...'
q.join();print 'Done'
在上面程式碼中使用subprocess的主要好處是,使用多個執行緒來執行ping命令會節省大量時間。
假設說我們用一個執行緒來處理,那麼每個 ping都要等待前一個結束之後再ping其他地址。那麼如果有100個地址,一共需要的時間=100*平均時間。
如果使用多個執行緒,那麼最長執行時間的執行緒就是整個程式執行的總時間。【時間比單個執行緒節省多了】
這裡要注意一下Queue模組的學習。
pingme函式的執行是這樣的:
啟動的執行緒會去執行pingme函式。
pingme函式會檢測佇列中是否有元素。如果有的話,則取出並執行ping命令。
這個佇列是多個執行緒共享的。所以這裡我們不使用列表。【假設在這裡我們使用列表,那麼需要我們自己來進行同步控制。Queue本身已經通過訊號量做了同步控制,節省了我們自己做同步控制的工作=。=】
程式碼中q的join函式是阻塞當前執行緒。下面是e文註釋
Queue.join()
Blocks until all items in the queue have been gotten and processed(task_done()).
---------------------------------------------
學習Processing模組的時候,遇到了程式的join函式。程式的join函式意思說,等待程式執行結束。與這裡的Queue的join有異曲同工之妙啊。processing模組學習的文章在這裡
轉載來自:http://blog.csdn.net/imzoer/article/details/8678029相關文章
- Python模組學習:subprocess 建立子程式Python
- python subprocessPython
- python之subprocessPython
- python Subprocess 模組Python
- 【Python】模組之subprocessPython
- python中的字典學習Python
- python如何呼叫subprocess模組實現外部命令?Python
- python中使用subprocess批量執行linux下命令PythonLinux
- python中使用subprocess批次執行linux下命令PythonLinux
- Python 快速教程(標準庫06):子程式 (subprocess包)Python
- 學習python多久?該如何學習python?Python
- 跨行業如何學習好python?Python學習!行業Python
- 如何高效的學習python?python學習技巧Python
- Python如何快速學習?Python學習方法技巧!Python
- PYTHON 學習Python
- 學習pythonPython
- python學習Python
- subprocess中命令為引數序列和字串的區別字串
- python中web開發框架Django的學習PythonWeb框架Django
- 學習Python中的一些小遊戲Python遊戲
- python的學習(三)----中括號的使用Python
- 深度學習——學習目錄——學習中……深度學習
- 你適合學習python嗎?python學習人群Python
- 如何學習Python?Python學習入門路線Python
- python os.system、os.popen、subprocess.Popen的區別Python
- 【python系統學習17】python中的檔案讀寫Python
- Python中列表、元組、字典有何區別?Python學習!Python
- Python中tuple和list的區別?Python基礎學習!Python
- 學習Python需要考證嗎?Python學習入門!Python
- python值得學習嗎?為何推薦學習python?Python
- 學習Python需要注意什麼?如何學習Python?Python
- python學習: 如何循序漸進學習Python語言Python
- Python 中級學習之函式裝飾器Python函式
- python 中的正規表示式學習筆記Python筆記
- Python深度學習Python深度學習
- [python]pandas學習Python
- python學習1Python
- python學習《一》Python