線程和進程——python的多線程

來源:互聯網
上載者:User

標籤:集合   關於   訪問   dump   網路架構   技術   append   解析   效率   

    首先要分清楚這兩個概念。

    

    進程:一個具有獨立功能的程式關於某個資料集合的一次運行活動。其一,它是一個實體;其二,是一個“執行中的程式”。

    線程:進程裡包含的執行單元叫線程,一個進程可以包含多個線程。它是cpu的基本調度單位。

    一個進程的記憶體空間是可以被它的線程共用的,但是一個線程在使用時,其它線程必須等待。通過“鎖”防止多個線程同時佔用空間。

 

    在不同線程同時訪問時,資料的保護機制是怎樣的呢?這就要提到python的一個“鎖”——GIL(全稱為全域解譯器鎖),要想利用多核系統,Python必須支援多線程運行。作為解釋型語言,Python的解譯器必須做到既安全又高效。我們都知道多線程編程會遇到的問題。解譯器要留意的是避免在不同的線程操作內部共用的資料。同時它還要保證在系統管理使用者線程時保證總是有最大化的計算資源。所以python就有了這麼一個“鎖”。這是一個讓人頭疼的問題,“鎖”的存在解決了那一些麻煩,但是也犧牲了python的多線程能力。

 

    python的多線程適合於:大量密集的I/O處理

    python的多進程:大量的密集並行計算

    儘管python的多線程功能看起來比較雞肋,但是在爬蟲中的應用,還是可以提高效率的。

 

  1 import requests  2 import threading    #使用線程庫  3 from queue import Queue  4 from lxml import etree  5 import json  6 import time  7   8   9 class ThreadCrawl(threading.Thread): 10     def __init__(self,threadName,pageQueue,dataQueue): 11  12         threading.Thread.__init__(self) 13     #調用父類初始化方法 14     #super(ThreadCrawl,self).__init__() 15         self.threadName=threadName 16         self.pageQueue=pageQueue 17         self.dataQueue=dataQueue 18         self.headers={"User-Agent":"Mozilla/5.0(Macintosh;IntelMacOSX10_7_0)AppleWebKit/535.11(KHTML,likeGecko)Chrome/17.0.963.56Safari/535.11"} 19  20  21     def run(self): 22          pass 23                 self.dataQueue.put(content) 24  25             except: 26                 pass 27         print("結束" + self.threadName) 28  29 class ThreadParse(threading.Thread): 30     def __init__(self,threadName,dataQueue,filename,lock): 31         super(ThreadParse,self).__init__() 32         self.threadName=threadName 33         self.dataQueue=dataQueue 34         self.filename=filename 35         self.lock=lock 36  37  38     def run(self): 39         pass 40  41     def parse(self,html): 42         pass 43         with self.lock: 44             self.filename.write(json.dumps(items,ensure_ascii=False).encoding("utf-8") + "\n") 45  46  47  48  49 grasp_exit=False 50 parse_exit=False 51  52  53  54 def main(): 55     #設定頁碼隊列 56     pageQueue=Queue(20) 57     #放入1-10個數字,按照隊列的先進先出原則 58     for i in range(1,21): 59         pageQueue.put(i) 60  61     #採集結果的隊列,為空白則表示無限制 62     dataQueue=Queue() 63      64     filename=open("lagou.json","a") 65  66     #建立鎖 67     lock=threading.Lock() 68  69  70     #採集線程 71     graspList=["採集線程1","採集線程2","採集線程3"] 72     #儲存線程 73     threadcrawl=[] 74     for threadName in graspList: 75         thread=ThreadCrawl(threadName,pageQueue,dataQueue) 76         thread.start() 77         threadcrawl.append(thread) 78  79     #解析線程 80     parseList=["解析線程1","解析線程2","解析線程3"] 81     #儲存線程 82     threadparse=[] 83     for threadName in parseList: 84         thread=ThreadParse(threadName,dataQueue,filename,lock) 85         thread.start() 86         threadparse.append(thread) 87  88     while not pageQueue.empty(): 89         pass 90  91  92     global grasp_exit 93     grasp_exit=True 94  95     print("隊列為空白") 96  97  98     for thread in threadcrawl: 99         thread.join()100 101     while not dataQueue.empty():102         pass103 104     global parse_exit105     parse_exit=True106 107     for thread in threadparse:108         thread.join()109     with lock:110         filename.close() 111 if __name__=="__main__":112     main()

    上面是以拉勾網為例,寫了一個多線程。代碼不全,完整代碼參考我的github。效果如下:

 

    多線程能提高的效率是有限的,後期會使用非同步網路架構如scrapy來提高爬蟲效率。

線程和進程——python的多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.