Python爬蟲程序中使用生產(chǎn)者與消費(fèi)者模式時(shí)進(jìn)程過早退出的問題
之前寫爬蟲程序的時(shí)候,采用生產(chǎn)者和消費(fèi)者的模式,利用Queue作為生產(chǎn)者進(jìn)程和消費(fèi)者進(jìn)程之間的同步隊(duì)列。
執(zhí)行程序時(shí),總是秒退,加了斷點(diǎn)也無法中斷,加打印也無法輸出,我知道肯定是進(jìn)程退出了,但還是百思不得解,為什么會(huì)這么快就退出。
一開始以為是我的進(jìn)程代碼寫的有問題,在某個(gè)地方崩潰導(dǎo)致程序提前退出,排查了一遍又一遍,并沒有發(fā)現(xiàn)什么明顯的問題,后來走讀代碼,看到主模塊中消費(fèi)者和生產(chǎn)者進(jìn)程的啟動(dòng)后,發(fā)現(xiàn)了問題,原因是我通過start()方法啟動(dòng)進(jìn)程后,使用join()的方式有問題。消費(fèi)者進(jìn)程必須執(zhí)行join()操作,否則消費(fèi)者進(jìn)程將在有時(shí)間完成所有工作之前被終止。
錯(cuò)誤的示范:
queue = multiprocessing.JoinableQueue() consumer = PageContentConsumer(queue) consumer.start() producer = PageContentProducer(queue) producer.start() # 想通過queue的join()方法確保queue中的元素都被處理完畢 # 但從實(shí)際運(yùn)行看,消費(fèi)者進(jìn)程還沒來得及處理就退出了 queue.join()
正確的示范:
queue = multiprocessing.JoinableQueue() consumer = PageContentConsumer(queue) consumer.start() producer = PageContentProducer(queue) producer.start() # 需要執(zhí)行producer.join(),確保生產(chǎn)者進(jìn)程能夠持續(xù)執(zhí)行 producer.join() # 需要執(zhí)行consumer.join(),確保消費(fèi)者進(jìn)程有時(shí)間進(jìn)行處理 consumer.join() # 通過queue的join()方法確保queue中的元素都被處理完畢, 這一步可選,因?yàn)檎鎸?shí)代碼里放了隊(duì)列完成標(biāo)志 queue.join()
生產(chǎn)者進(jìn)程示意代碼:
class PageContentProducer(multiprocessing.Process): ? ? def __init__(self, page_list:list, output_queue:multiprocessing.JoinableQueue): ? ? ? ? multiprocessing.Process.__init__(self) ? ? ? ? self.daemon = True ? ? ? ? self.page_list = page_list ? ? ? ? self.content_list = [] ?# 用于保存匯總信息,沒有什么實(shí)際作用 ? ? ? ? self.output_queue = output_queue ? ?? ? ? def run(self): ? ? ? ? ''' ? ? ? ? 向隊(duì)列中加入每一篇文章 ? ? ? ? ''' ? ? ? ? self.visit_all_page_to_get_content() ? ? ? ?? ? ? def visit_all_page_to_get_content(self): ? ? ? ? ''' ? ? ? ? 使用線程池處理所有的page, 并從每一頁上提取所有的文章content ? ? ? ? ''' ? ? ? ? ...
消費(fèi)者進(jìn)程示意代碼:
class PageContentConsumer(multiprocessing.Process): ? ? def __init__(self, dir, input_queue:multiprocessing.JoinableQueue): ? ? ? ? multiprocessing.Process.__init__(self) ? ? ? ? self.daemon = True ? ? ? ? self.input_queue = input_queue ? ? ? ? self.dir = dir ? ? ? ?? ? ? def run(self): ? ? ? ? while True: ? ? ? ? ? ? try: ? ? ? ? ? ? ? ? content = self.input_queue.get() ? ? ? ? ? ? ? ? if content is None: ? ? ? ? ? ? ? ? ? ? # 如果收到結(jié)束標(biāo)志, 就退出當(dāng)前任務(wù) ? ? ? ? ? ? ? ? ? ? break ? ? ? ? ? ? ? ? self.content_worker_func(self.dir, content) ? ? ? ? ? ? ? ? print(f"已處理: {content['title']}") ? ? ? ? ? ? ? ? # 發(fā)出信號通知任務(wù)完成 ? ? ? ? ? ? ? ? self.input_queue.task_done() ? ? ? ? ? ? except Exception as e: ? ? ? ? ? ? ? ? print(repr(e)) ? ? ? ? ? ? ? ?? ? ? def content_worker_func(self, dir, content): ? ? ? ? ''' ? ? ? ? 主要工作函數(shù) ? ? ? ? ''' ? ? ? ? ...
主模塊代碼示意如下:
if __name__ == '__main__': ? ? page_list = [xxxx] ? ?? ? ? queue = multiprocessing.JoinableQueue() ? ?? ? ? consumer_num = os.cpu_count() ? ? consumers = [] ? ?? ? ? for i in range(0, consumer_num): ? ? ? ? consumers.append(PageContentConsumer(dir, queue)) ? ?? ? ? for i in range(0, consumer_num): ? ? ? ? consumers[i].start() ? ?? ? ? producer = PageContentProducer(page_list, queue) ? ? producer.start() ? ? producer.join() ? ?? ? ? # 在隊(duì)列上放置標(biāo)志,發(fā)出完成信號, 有幾個(gè)消費(fèi)者,就需要放置多少個(gè)標(biāo)志 ? ? for i in range(0, consumer_num): ? ? ? ? queue.put(None) ? ? ? ?? ? ? # 等待消費(fèi)者進(jìn)程關(guān)閉 ? ? for i in range(0, consumer_num): ? ? ? ? consumers[i].join()
到此這篇關(guān)于Python爬蟲程序中使用生產(chǎn)者與消費(fèi)者模式時(shí)進(jìn)程過早退出的問題的文章就介紹到這了,更多相關(guān)Python生產(chǎn)者與消費(fèi)者模式進(jìn)程早退內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python7個(gè)爬蟲小案例詳解(附源碼)中篇
- Python7個(gè)爬蟲小案例詳解(附源碼)上篇
- Python爬蟲庫urllib的使用教程詳解
- Python利用yield?form實(shí)現(xiàn)異步協(xié)程爬蟲
- python爬蟲之requests庫使用代理方式
- python?基于aiohttp的異步爬蟲實(shí)戰(zhàn)詳解
- Python爬蟲框架NewSpaper使用詳解
- 通過python爬蟲mechanize庫爬取本機(jī)ip地址的方法
- Python爬蟲學(xué)習(xí)之requests的使用教程
- python爬蟲beautiful?soup的使用方式
- Python爬蟲之超級鷹驗(yàn)證碼應(yīng)用
- Python爬蟲Requests庫的使用詳情
- python爬蟲模擬登錄之圖片驗(yàn)證碼實(shí)現(xiàn)詳解
- Python爬蟲eval實(shí)現(xiàn)看漫畫漫畫柜mhgui實(shí)戰(zhàn)分析
- python爬蟲實(shí)戰(zhàn)項(xiàng)目之爬取pixiv圖片
- 使用python爬蟲實(shí)現(xiàn)子域名探測問題
- python爬蟲之代理ip正確使用方法實(shí)例
- Python7個(gè)爬蟲小案例詳解(附源碼)下篇
相關(guān)文章
Python實(shí)現(xiàn)計(jì)算長方形面積(帶參數(shù)函數(shù)demo)
今天小編就為大家分享一篇Python實(shí)現(xiàn)計(jì)算長方形面積(帶參數(shù)函數(shù)demo),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01對Python 網(wǎng)絡(luò)設(shè)備巡檢腳本的實(shí)例講解
下面小編就為大家分享一篇對Python 網(wǎng)絡(luò)設(shè)備巡檢腳本的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04使用Dajngo 通過代碼添加xadmin用戶和權(quán)限(組)
這篇文章主要介紹了使用Dajngo 通過代碼添加xadmin用戶和權(quán)限(組),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07python 普通克里金(Kriging)法的實(shí)現(xiàn)
這篇文章主要介紹了python 普通克里金(Kriging)法的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Python閉包執(zhí)行時(shí)值的傳遞方式實(shí)例分析
這篇文章主要介紹了Python閉包執(zhí)行時(shí)值的傳遞方式,結(jié)合實(shí)例形式分析了Python閉包執(zhí)行時(shí)的傳值原理與實(shí)現(xiàn)方式,代碼中包含了較為詳盡的注釋便于理解,需要的朋友可以參考下2018-06-06