美文网首页
获取 异步执行调用的结果

获取 异步执行调用的结果

作者: eeert2 | 来源:发表于2020-04-18 14:13 被阅读0次

    在我的多进程 multiprocessing.Process有同学留言 如何获取 子进程处理的结果。这里开一篇博客讲解。

    其实这里涉及到同步异步的概念。对于多线程/进程 而言,它们其实是一种异步操作。

    对于异步操作,分为不需要获取异步结果需要获取异步结果,我们应该尽量设计成第一种方式。

    一、不需要获取异步返回结果

    对于大部分的 多线程/进程异步操作[后面统称为异步操作],我们应尽量在异步操作中完成所有任务,这是可以通过设计控制的。

    举例几个场景:

    1. 在前端的数据加载过程,我们会发送异步ajax请求并获取数据,这个时候我们不应该让主控流程等待异步加载的结果,获取结果后再渲染到页面上。
      正确的做法是将 获取 + 渲染 的任务都放到异步操作中,主控流程只负责发送异步请求,然后多个异步请求各自完成自己的任务。

    2)多个线程/进程异步有关联的操作。
    多线程 / 进程有一个经典的入门案例:生产者与消费者模式。

    按照同步的思想,应该是[在主控程序中]通过生产者获取数据,然后调用消费者去消耗数据。

    但是在多线程 |进程中,我们应该在子线程中完成任务。所以应该这样设计:
    生产者消费者中分别传入一个容器,他们分别在容器中put,get数据

    """模拟生产者,消费者"""
    from multiprocessing import Process, Queue
    import time, random
    
    
    def create(queue: Queue):
        """具有生产功能的函数
    
        向 queue 中添加 url 网址
        """
        for value in range(100):
            # 随机停顿 0 - 1秒,模拟生产者的生产动作
            time.sleep(random.random())
            value = 'http://www.baidu.com/' + str(value) + '/'
            queue.put(value)
    
    
    def consume(queue: Queue):
        """具有消费功能的函数
    
        从 queue 中消耗数据 url 数据
        """
        while True:
            value = queue.get()
            print('向目标 url 爬取数据:' + value)
    
    
    if __name__ == '__main__':
        # 主控流程
        url_pool = Queue(maxsize=10)
        creater = Process(target=create, args=(url_pool,))
        consumer = Process(target=consume, args=(url_pool,))
    
        creater.start()
        consumer.start()
    

    小结,对于大部分的IO操作,使用多线程/进程可以大大的减少程序执行时间,在设计多线程/进程时,我们应尽量将任务在子线程/进程中完成。

    作为一个成熟的子线程/进程,你应该能够独立完成工作。包含数据处理,存储,异常等待。

    一个子线程处理的任务量可大可小。我们可以通过一个子线程发送邮件,对服务器而言,可以通过一个子线程去处理用户请求,我们后端的所以操作都是在这个子线程中完成。

    二、需要获取异步结果

    虽然上面讲了很多的不需要获取异步结果的案例。当我们也有很多必须要获取异步结果的场景。

    比如我们将一个很大的计算分成多个小计算,然后对这些小计算的结果汇总。
    比如做大文件上传,将大文件拆分成小文件,并获取上传成功的小文件标示 ...

    对于需要获取异步结果场景,python有单独的多线程/进程执行器,分别是
    ProcessPoolExecutor,ThreadPoolExecutor

    from concurrent.futures import ProcessPoolExecutor
    import time
    
    def long_compute_sum(v1: int, v2: int):
        """需要计算很长[3秒]的加法"""
        time.sleep(3)
        return v1 + v2
    
    
    if __name__ == '__main__':
        executor = ProcessPoolExecutor(max_workers=4)
        future = executor.submit(long_compute_sum, 100, 200)  # 获取期程对象
        print(future.result())  # 从期程对象中获取返回结果
    

    相关文章

      网友评论

          本文标题:获取 异步执行调用的结果

          本文链接:https://www.haomeiwen.com/subject/efhvvhtx.html