Python爬虫程序中使用生产者与消费者模式时进程过早退出的问题

 更新时间:2023年01月06日 10:34:18   作者:smart_cat  
本文主要介绍了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()

到此这篇关于Python爬虫程序中使用生产者与消费者模式时进程过早退出的问题的文章就介绍到这了,更多相关Python生产者与消费者模式进程早退内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python常见错误:IndexError: list index out of range解决

    Python常见错误:IndexError: list index out of range解决

    最近在写一个爬虫程序,但是却出现了错误提示IndexError: list index out of range,所以下面这篇文章主要给大家介绍了关于Python常见错误:IndexError: list index out of range的解决方法,需要的朋友可以参考下
    2023-01-01
  • Python+Pygame实战之炫舞小游戏的实现

    Python+Pygame实战之炫舞小游戏的实现

    提到QQ炫舞,可能很多人想到的第一个词是“青春”。恍然间,这个承载了无数人回忆与时光的游戏品牌,已经走到了第十几个年头。今天小编就来给大家尝试做一款简单的简陋版的小游戏——《舞动青春*炫舞》,感兴趣的可以了解一下
    2022-12-12
  • pandas apply多线程实现代码

    pandas apply多线程实现代码

    这篇文章主要介绍了pandas apply多线程实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • 解决Python命令行下退格,删除,方向键乱码(亲测有效)

    解决Python命令行下退格,删除,方向键乱码(亲测有效)

    今天小编就为大家分享一篇解决Python命令行下退格,删除,方向键乱码(亲测有效),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • python 中os模块os.path.exists()的用法说明

    python 中os模块os.path.exists()的用法说明

    这篇文章主要介绍了python 中os模块os.path.exists()的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • python的scrapy框架之Pipeline文件的用法详解

    python的scrapy框架之Pipeline文件的用法详解

    这篇文章主要介绍了python的scrapy框架之Pipeline文件的用法详解,Pipeline是一个独立的模块,用于处理从Spider中提取的Item对象,实现对数据的进一步处理、存储和清洗等操作,下面将详细介绍Scrapy框架中Pipeline的用法,需要的朋友可以参考下
    2023-10-10
  • 用python给csv里的数据排序的具体代码

    用python给csv里的数据排序的具体代码

    在本文里小编给大家分享的是关于用python给csv里的数据排序的具体代码内容,需要的朋友们可以学习下。
    2020-07-07
  • Python编程实现输入某年某月某日计算出这一天是该年第几天的方法

    Python编程实现输入某年某月某日计算出这一天是该年第几天的方法

    这篇文章主要介绍了Python编程实现输入某年某月某日计算出这一天是该年第几天的方法,涉及Python针对日期时间的转换与运算相关操作技巧,需要的朋友可以参考下
    2017-04-04
  • Python实现单例模式的五种写法总结

    Python实现单例模式的五种写法总结

    单例模式(Singleton Pattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。本文为大家整理了五种Python实现单例模式的写法,需要的可以参考一下
    2022-08-08
  • Python构造函数及解构函数介绍

    Python构造函数及解构函数介绍

    这篇文章主要介绍了Python构造函数及解构函数介绍,本文只是讲解构造及解构函数的简单知识,需要的朋友可以参考下
    2015-02-02

最新评论