python執行緒池(threadpool)模組使用
阿新 • • 發佈:2018-12-30
最近碰到個問題,需要telnet登入上千臺機器去取主機名;其中有使用者名稱密碼互動部分,有需要延遲的部分,大概一次登入一次到處理完要10s,1000臺機器序列處理就需要1000×10s,差不多三個小時,這是很難受的事情;
之前用thread的start_new_thread方法也可以實現,但是執行緒數量不好控制,沒找到相關的控制執行緒數量的鎖;
找了下關於python的執行緒池,找到threadpool這麼一個模組,可以滿足我的需求,見:
http://chrisarndt.de/projects/threadpool/
我下的是版本1.2.2:
http://chrisarndt.de/projects/threadpool/download/threadpool-1.2.2.tar.bz2
放到當前目錄或者python模組庫都行,用法很簡單,見:
Basic usage::
>>> pool = ThreadPool(poolsize)
>>> requests = makeRequests(some_callable, list_of_args, callback)
>>> [pool.putRequest(req) for req in requests]
>>> pool.wait()
第一行定義了一個執行緒池,表示最多可以建立poolsize這麼多執行緒;
第二行是呼叫makeRequests建立了要開啟多執行緒的函式,以及函式相關引數和回撥函式,其中回撥函式可以不寫,default是無,也就是說makeRequests只需要2個引數就可以執行;
第三行用法比較奇怪,是將所有要執行多執行緒的請求扔進執行緒池,[pool.putRequest(req) for req in requests]等同於:
for req in requests:
pool.putRequest(req)
第四行是等待所有的執行緒完成工作後退出;
下面看下我的程式碼,使用執行緒池前後程式碼對比,不使用執行緒池:
如果myTelnet每次執行要10s,那麼255次myTelnet就需要2550s,大概是40分鐘;import telnetlib import time #執行比較耗時的函式,需要開啟多執行緒 def myTelnet(L): tn = telnetlib.Telnet(L[0]) time.sleep(2) ... idx = tn.expect(["Username:", "login:"], timeout=5) ... time.sleep(3) x = tn.read_very_eager() tn.close() ... return #模擬255個ip,需要逐個登入的函式 def myIpPool(ipPrefix): List=[] for i in range(1, 255): List.append("%s.%d" % (ipPrefix, i)) return List #序列執行telnet登入 L=myIpPool("200.200.200") for i in range(len(L)): myTelnet(L[i])
用多執行緒的情況:
import telnetlib
import time
import threadpool
#執行比較耗時的函式,需要開啟多執行緒
def myTelnet(L):
tn = telnetlib.Telnet(L[0])
time.sleep(2)
...
idx = tn.expect(["Username:", "login:"], timeout=5)
...
time.sleep(3)
x = tn.read_very_eager()
tn.close()
...
return
#模擬255個ip,需要逐個登入的函式
def myIpPool(ipPrefix):
List=[]
for i in range(1, 255):
List.append("%s.%d" % (ipPrefix, i))
return List
#使用多執行緒執行telnet函式
pool = threadpool.ThreadPool(10)
requests = threadpool.makeRequests(myTelnet, L)
[pool.putRequest(req) for req in requests]
pool.wait()
output.close()
開始是個執行緒,理論上應該快10倍,實際可能沒這麼快,我將myTelnet函式改成只的sleep 10秒,什麼也不幹,測了下執行完需要260s,幾乎是10倍的速度;改成如下:
pool = threadpool.ThreadPool(30)
90s執行完畢,說明執行緒池還是很有用的東西