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執行完畢,說明執行緒池還是很有用的東西

Tags: