這篇文章主要介紹“Python多線(xiàn)程爬蟲(chóng)舉例分析”,在日常操作中,相信很多人在Python多線(xiàn)程爬蟲(chóng)舉例分析問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”P(pán)ython多線(xiàn)程爬蟲(chóng)舉例分析”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
達(dá)茂旗網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。成都創(chuàng)新互聯(lián)公司從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專(zhuān)注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。
當(dāng)程序在運(yùn)行時(shí),就會(huì)創(chuàng)建包含代碼和狀態(tài)的進(jìn)程。這些進(jìn)程通過(guò)一個(gè)或者多個(gè)CPU來(lái)執(zhí)行。不過(guò)同一時(shí)刻每個(gè)CPU只會(huì)執(zhí)行一個(gè)進(jìn)程,然后在不同進(jìn)程之間快速切換,這樣就感覺(jué)多個(gè)程序同時(shí)運(yùn)行。同理,在一個(gè)進(jìn)程中,程序的執(zhí)行也是在不同線(xiàn)程間進(jìn)行切換的,每個(gè)線(xiàn)程執(zhí)行程序的不同部分。這就意味著一個(gè)線(xiàn)程在等待執(zhí)行時(shí),進(jìn)程會(huì)切換到其他的線(xiàn)程執(zhí)行,這樣可以避免浪費(fèi)CPU時(shí)間。
在Python標(biāo)準(zhǔn)庫(kù)中,使用threading模塊來(lái)支持多線(xiàn)程。Threading模塊對(duì)thread進(jìn)行了封裝,絕大數(shù)情況,只需要使用threading這個(gè)模塊。使用起來(lái)也非常簡(jiǎn)單:
t1=threading.Thread(target=run,args=("t1",)) 創(chuàng)建一個(gè)線(xiàn)程實(shí)例 # target是要執(zhí)行的函數(shù)名(不是函數(shù)),args是函數(shù)對(duì)應(yīng)的參數(shù),以元組的形式存在 t1.start() 啟動(dòng)這個(gè)線(xiàn)程實(shí)例。
線(xiàn)程的創(chuàng)建很簡(jiǎn)單,如下:
import threading import time def printStr(name): print(name+"-python青燈") s=0.5 time.sleep(s) print(name+"-python青燈") t1=threading.Thread(target=printStr,args=("你好!",)) t2=threading.Thread(target=printStr,args=("歡迎你!",)) t1.start() t2.start()
本質(zhì)是繼承threading.Thread,重構(gòu)Thread類(lèi)中的run方法
import threading import time class testThread(threading.Thread): def __init__(self,s): super(testThread,self).__init__() self.s=s def run(self): print(self.s+"——python") time.sleep(0.5) print(self.s+"——青燈") if __name__=='__main__': t1=testThread("測(cè)試1") t2=testThread("測(cè)試2") t1.start() t2.start()
使用setDaemon(True)把子線(xiàn)程都變成主線(xiàn)程的守護(hù)線(xiàn)程,因此當(dāng)主線(xiàn)程結(jié)束后,子線(xiàn)程也會(huì)隨之結(jié)束。也就是說(shuō),主線(xiàn)程不等待其守護(hù)線(xiàn)程執(zhí)行完成再去關(guān)閉。
import threading import time def run(s): print(s,"python") time.sleep(0.5) print(s,"青燈") if __name__ == "__main__": t=threading.Thread(target=run,args=("你好!",)) t.setDaemon(True) t.start() print("end")
結(jié)果:
你好! python
end
當(dāng)主線(xiàn)程結(jié)束后,守護(hù)線(xiàn)程不管有沒(méi)有結(jié)束,都自動(dòng)結(jié)束。
使用join方法,讓主線(xiàn)程等待子線(xiàn)程執(zhí)行。如下:
import threading import time def run(s): print(s,"python") time.sleep(0.5) print(s,"青燈") if __name__ == "__main__": t=threading.Thread(target=run,args=("你好!",)) t.setDaemon(True) t.start() t.join() print("end")
結(jié)果:
你好! python
你好! 青燈
end
以上是多線(xiàn)程的幾種簡(jiǎn)單的用法,那么threading模塊還有做什么呢?請(qǐng)往下看。
其實(shí)在介紹diskcache緩存的時(shí)候也介紹過(guò)鎖的相關(guān)內(nèi)容,其實(shí)不難理解為啥多線(xiàn)程中也會(huì)出現(xiàn)鎖的概念,當(dāng)沒(méi)有保護(hù)共享資源時(shí),多個(gè)線(xiàn)程在處理同一資源時(shí),可能會(huì)出現(xiàn)臟數(shù)據(jù),造成不可以預(yù)期的結(jié)果,即線(xiàn)程不安全。
如下示例出現(xiàn)不可預(yù)期的結(jié)果:
import threading price=0 def changePrice(n): global price price=price+n price=price-n def runChange(n): for i in range(2000000): changePrice(n) if __name__ == "__main__": t1=threading.Thread(target=runChange,args=(5,)) t2=threading.Thread(target=runChange,args=(8,)) t1.start() t2.start() t1.join() t2.join() print(price)
理論上的結(jié)果為0,但是每次運(yùn)行的結(jié)果可能都是不一樣的。
所以這個(gè)時(shí)候就需要鎖去處理了,如下:
import threading import time from threading import Lock price=0 def changePrice(n): global price lock.acquire() #獲取鎖 price=price+n print("price:"+str(price)) price=price-n lock.release() #釋放鎖 def runChange(n): for i in range(2000000): changePrice(n) if __name__ == "__main__": lock=Lock() t1=threading.Thread(target=runChange,args=(5,)) t2=threading.Thread(target=runChange,args=(8,)) t1.start() t2.start() t1.join() t2.join() print(price)
結(jié)果值與理論值是一致的。鎖的意義在于每次只允許一個(gè)線(xiàn)程去修改同一數(shù)據(jù),以保證線(xiàn)程安全。
BoundedSemaphore類(lèi),同時(shí)允許一定數(shù)量的線(xiàn)程更改數(shù)據(jù),如下:
import threading import time def work(n): semaphore.acquire() print("序號(hào):"+str(n)) time.sleep(1) semaphore.release() if __name__ == "__main__": semaphore=threading.BoundedSemaphore(5) for i in range(100): t=threading.Thread(target=work,args=(i+1,)) t.start() #active_count獲取當(dāng)前正在運(yùn)行的線(xiàn)程數(shù) while threading.active_count()!=1: pass else: print("end")
結(jié)果為:每5次打印停頓一下,直到結(jié)束。
說(shuō)到多線(xiàn)程,不得不提一下GIL。GIL的全稱(chēng)是Global Interpreter Lock(全局解釋器鎖),這是python設(shè)計(jì)之初,為了數(shù)據(jù)安全所做的決定。某個(gè)線(xiàn)程想要執(zhí)行,必須先拿到GIL,并且在一個(gè)進(jìn)程中,GIL只有一個(gè)。只有拿到GIL的線(xiàn)程,才能進(jìn)入CPU執(zhí)行。GIL只在cpython中才有,因?yàn)閏python調(diào)用的是c語(yǔ)言的原生線(xiàn)程,所以他不能直接操作cpu,只能利用GIL保證同一時(shí)間只能有一個(gè)線(xiàn)程拿到數(shù)據(jù)。而在pypy和jpython中是沒(méi)有GIL的。
到此,關(guān)于“Python多線(xiàn)程爬蟲(chóng)舉例分析”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
分享標(biāo)題:Python多線(xiàn)程爬蟲(chóng)舉例分析
本文路徑:http://aaarwkj.com/article26/pjcgcg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、網(wǎng)站策劃、App開(kāi)發(fā)、網(wǎng)站制作、網(wǎng)站排名、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)