广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python爬虫程序中使用生产者与消费者模式时进程过早退出的问题
  • 778
分享到

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

Python生产者与消费者模式进程早退Python进程早退 2023-01-06 12:01:46 778人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

之前写爬虫程序的时候,采用生产者和消费者的模式,利用Queue作为生产者进程和消费者进程之间的同步队列。 执行程序时,总是秒退,加了断点也无法中断,加打印也无法输出,我知道肯定是进程

之前写爬虫程序的时候,采用生产者和消费者的模式,利用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生产者与消费者模式进程早退内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

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

本文链接: https://www.lsjlt.com/news/176966.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作