python執行緒池(threadpool
- 2020 年 1 月 10 日
- 筆記
最近碰到個問題,需要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)
第四行是等待所有的執行緒完成工作後退出;
下面看下我的程式碼,使用執行緒池前後程式碼對比,不使用執行緒池:
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]) 如果myTelnet每次執行要10s,那麼255次myTelnet就需要2550s,大概是40分鐘;
用多執行緒的情況:
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執行完畢,說明執行緒池還是很有用的東西
