获取 异步执行调用的结果

2020-04-18  本文已影响0人  eeert2

在我的多进程 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())  # 从期程对象中获取返回结果
上一篇 下一篇

猜你喜欢

热点阅读