Python爬虫程序中使用生产者与消费者模式时进程过早退出的问题
作者:smart_cat 发布时间:2022-10-12 03:37:52
标签:Python,生产者,消费者,进程早退
之前写爬虫程序的时候,采用生产者和消费者的模式,利用Queue作为生产者进程和消费者进程之间的同步队列。
执行程序时,总是秒退,加了断点也无法中断,加打印也无法输出,我知道肯定是进程退出了,但还是百思不得解,为什么会这么快就退出。
一开始以为是我的进程代码写的有问题,在某个地方崩溃导致程序提前退出,排查了一遍又一遍,并没有发现什么明显的问题,后来走读代码,看到主模块中消费者和生产者进程的启动后,发现了问题,原因是我通过start()方法启动进程后,使用join()的方式有问题。消费者进程必须执行join()操作,否则消费者进程将在有时间完成所有工作之前被终止。
错误的示范:
queue = multiprocessing.JoinableQueue()
consumer = PageContentConsumer(queue)
consumer.start()
producer = PageContentProducer(queue)
producer.start()
# 想通过queue的join()方法确保queue中的元素都被处理完毕
# 但从实际运行看,消费者进程还没来得及处理就退出了
queue.join()
正确的示范:
queue = multiprocessing.JoinableQueue()
consumer = PageContentConsumer(queue)
consumer.start()
producer = PageContentProducer(queue)
producer.start()
# 需要执行producer.join(),确保生产者进程能够持续执行
producer.join()
# 需要执行consumer.join(),确保消费者进程有时间进行处理
consumer.join()
# 通过queue的join()方法确保queue中的元素都被处理完毕, 这一步可选,因为真实代码里放了队列完成标志
queue.join()
生产者进程示意代码:
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 = [] # 用于保存汇总信息,没有什么实际作用
self.output_queue = output_queue
def run(self):
'''
向队列中加入每一篇文章
'''
self.visit_all_page_to_get_content()
def visit_all_page_to_get_content(self):
'''
使用线程池处理所有的page, 并从每一页上提取所有的文章content
'''
...
消费者进程示意代码:
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:
# 如果收到结束标志, 就退出当前任务
break
self.content_worker_func(self.dir, content)
print(f"已处理: {content['title']}")
# 发出信号通知任务完成
self.input_queue.task_done()
except Exception as e:
print(repr(e))
def content_worker_func(self, dir, content):
'''
主要工作函数
'''
...
主模块代码示意如下:
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()
# 在队列上放置标志,发出完成信号, 有几个消费者,就需要放置多少个标志
for i in range(0, consumer_num):
queue.put(None)
# 等待消费者进程关闭
for i in range(0, consumer_num):
consumers[i].join()
来源:https://blog.csdn.net/hubing_hust/article/details/128362635
0
投稿
猜你喜欢
- 对图片进行resize、裁剪、旋转、翻转图片处理时常用的手段有resize、裁剪、旋转、翻转,简单介绍一下python中怎么利用PIL库和t
- 本文实例讲述了python中range()与xrange()用法。分享给大家供大家参考,具体如下:据说range比xrange开销要大,原因
- 一开始我使用了rarfile这个库,奈何对于含有密码的压缩包支持不好,在linux上不抛出异常;之后有又尝试了unrar。。比rarfile
- 在 MySQL 下,在进行中文模糊检索时,经常会返回一些与之不相关的记录,如查找 "%a%" 时,返回的可能有中文字符,
- 项目内容:用Python写的糗事百科的网络爬虫。使用方法:新建一个Bug.py文件,然后将代码复制到里面后,双击运行。程序功能:在命令提示行
- AJAX:Asynchronous JavaScript And XML--------异步JavaScript和XML
- 这篇文章主要介绍了Python scrapy增量爬取实例及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 利用python爬取豆瓣电影Top250的相关信息,包括电影详情链接,图片链接,影片中文名,影片外国名,评分,评价数,概况,导演,主演,年份
- 守来说,AJAX在现在是热得不能再热的技术。没有人能否认,它拥有大批的支持者。在CNN上,它从二月份的一个不被看好的词语到十月份成长成一个初
- 推荐使用 Homebrew 来安装第三方工具。自己安装的python散落在电脑各处,删除起来比较麻烦。今天在此记录一下删除的过程(本人以Py
- 一.filter函数简介filter函数主要用来筛选数据,过滤掉不符合条件的元素,并返回一个迭代器对象,如果要转换为列表list或者元祖tu
- python2.7,下面是跑在window上的,稍作修改就可以跑在linux上。实测win7和raspbian均可,且raspbian可以直
- Python有两个用于相等比较的运算符,“is”和“==”(等于)。在这篇文章中,我将教你们两者之间的区别,以及通过几个简单地例子说明什么时
- 首先,我们来看一个Python抓取网页的库:urllib或urllib2。那么urllib与urllib2有什么区别呢?可以把urllib2
- 实战场景这次被我们盯上的平台是【SMZDM】。本次目标站点是:aHR0cHM6Ly93d3cuc216ZG0uY29tLw==。正式开始前,
- 昨天同事无意又谈起了这个老话题,美工和设计师(视觉)有什么不同?以文字排版设计为例,列了下面两个图来说明,可能会有一些启发, 第一个图应该算
- 框架特色:一、统一命名空间 默认命名空间为F,当然你也可以改成自己喜欢的名字,整个框架
- Python等工具确实是不错的工具,但是有时候不管是基础的Python还是Python的软件包都让我觉得对中文不是很亲近。时不时地遇到一点问
- 最近在老家找工作,无奈老家工作真心太少,也没什么面试机会,不过之前面试一家公司,提了一个有意思的需求,检测河面没有有什么船只之类的物体,我当
- 本文实例讲述了Python3.5装饰器原理及应用。分享给大家供大家参考,具体如下:1、装饰器:(1)本质:装饰器的本质是函数,其基本语法都是