Python 获取多线程返回值的两种方式

本文介绍了两种在Python中使用线程进行并行计算的方法:一种是通过重写Thread类并自定义get_result()方法来获取线程的返回值;另一种是使用全局变量来实现线程间的数据共享。第一种方法虽然实现起来稍微复杂一些,但提供了更清晰的线程管理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 通过复写Thread类,自定义一个get_result()方法

from threading import Thread


# _sum = 0


def cal_sum(begin, end):
    # global _sum
    _sum = 0
    for i in range(begin, end + 1):
        _sum += i
    return  _sum

"""重新定义带返回值的线程类"""


class MyThread(Thread):
    def __init__(self, func, args):
        super(MyThread, self).__init__()
        self.func = func
        self.args = args

    def run(self):
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return None


if __name__ == '__main__':
    t1 = MyThread(cal_sum, args=(1, 5))
    t2 = MyThread(cal_sum, args=(6, 10))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    res1 = t1.get_result()
    res2 = t2.get_result()

    print(res1 + res2)

2. 使用全局变量

from threading import Thread

_sum = 0


def cal_sum(begin, end):
    # 声明使用全局变量
    global _sum
    for i in range(begin, end + 1):
        _sum += i


if __name__ == '__main__':
    t1 = Thread(target=cal_sum, args=(1, 5))
    t2 = Thread(target=cal_sum, args=(6, 10))
    t1.start()
    t2.start()

    print(_sum)

第二种方法简单一些,我个人还是比较喜欢用第一种方式。

<think>我们有两个主要模块可以获取多线程函数的返回值:`threading` 和 `concurrent.futures`。下面分别介绍两种方法。 ### 方法一:使用 `threading` 模块 在 `threading` 模块中,我们可以通过继承 `Thread` 类重写 `run` 方法,然后添加一个属性(如 `result`)来存储返回值。但是,更直接的方式是使用一个可调用对象(如函数)来捕获返回值。不过,`Thread` 类本身不提供直接获取返回值的机制。因此,我们可以通过以下方式实现: 1. 自定义一个线程类,在 `run` 方法中存储返回值。 2. 或者,使用一个共享的数据结构(如队列)来存储返回值。 这里我们使用队列(`queue.Queue`)来获取返回值,因为这种方法更通用且易于理解。 ```python import threading import queue def worker(num, result_queue): """线程执行函数,将结果放入队列""" result = num * num result_queue.put(result) # 创建队列用于存储结果 result_queue = queue.Queue() threads = [] # 创建启动多个线程 for i in range(5): t = threading.Thread(target=worker, args=(i, result_queue)) threads.append(t) t.start() # 等待所有线程完成 for t in threads: t.join() # 从队列中获取结果 results = [] while not result_queue.empty(): results.append(result_queue.get()) print(results) # 输出: [0, 1, 4, 9, 16] ``` ### 方法二:使用 `concurrent.futures` 模块 `concurrent.futures` 模块提供了更高级的接口,其中的 `ThreadPoolExecutor` 可以方便地管理线程获取返回值。我们使用 `submit` 方法提交任务,然后通过返回的 `Future` 对象获取结果。 ```python from concurrent.futures import ThreadPoolExecutor def worker(num): return num * num # 使用线程池,max_workers指定最大线程数 with ThreadPoolExecutor(max_workers=5) as executor: # 提交任务,返回Future对象 futures = [executor.submit(worker, i) for i in range(5)] # 获取结果 results = [future.result() for future in futures] print(results) # 输出: [0, 1, 4, 9, 16] ``` 或者,我们可以使用 `map` 方法,更简洁: ```python with ThreadPoolExecutor() as executor: results = list(executor.map(worker, range(5))) print(results) # 输出: [0, 1, 4, 9, 16] ``` ### 两种方法的比较 - **`threading` 模块**:需要手动管理线程结果队列,适合需要更细粒度控制的场景。 - **`concurrent.futures` 模块**:提供了更高级的抽象,使用简单,特别是获取返回值非常方便,推荐使用。 ### 注意事项 1. 在使用多线程时,需要注意线程安全,特别是在操作共享资源时。 2. 由于全局解释器锁(GIL)的存在,Python多线程在CPU密集型任务中可能无法充分利用多核优势,此时可以考虑使用多进程(`multiprocessing` 或 `ProcessPoolExecutor`)。 ### 引用说明 `concurrent.futures` 模块的 `ThreadPoolExecutor` 是对线程池的高级封装,使用起来非常方便[^2][^4]。而 `threading` 模块需要手动处理线程结果收集[^3]。 §§相关问题§§ 1. 如何获取多进程(multiprocessing)中函数的返回值? 2. 在 `concurrent.futures` 中,`map` 和 `submit` 方法有什么区别? 3. 如何处理多线程/多进程中的异常?</think>在 Python 中,获取多线程函数的返回值主要有两种方式:使用 `threading` 模块或 `concurrent.futures` 模块。以下是具体实现方法: ### 方法一:使用 `concurrent.futures`(推荐) `ThreadPoolExecutor` 提供了最简洁的返回值获取方式: ```python from concurrent.futures import ThreadPoolExecutor def task(n): return n * n # 返回计算结果 with ThreadPoolExecutor(max_workers=3) as executor: # 提交任务获取Future对象列表 futures = [executor.submit(task, i) for i in range(5)] # 获取所有任务结果(按完成顺序) results = [f.result() for f in futures] print(results) # 输出: [0, 1, 4, 9, 16] ``` 关键点: 1. `submit()` 返回 `Future` 对象,包含任务状态和结果 2. `result()` 方法阻塞获取返回值 3. 使用 `with` 语句自动管理线程池资源[^4] ### 方法二:使用 `threading` 模块 可通过自定义线程类或队列获取返回值: ```python import threading import queue def worker(n, result_queue): result_queue.put(n * n) # 将结果放入队列 result_queue = queue.Queue() threads = [] for i in range(5): t = threading.Thread(target=worker, args=(i, result_queue)) threads.append(t) t.start() # 等待所有线程完成 for t in threads: t.join() # 从队列获取结果 results = [] while not result_queue.empty(): results.append(result_queue.get()) print(results) # 输出: [0, 1, 4, 9, 16] ``` ### 两种方式对比 | 特性 | `concurrent.futures` | `threading` + 队列 | |----------------------|------------------------------|----------------------------| | **易用性** | ⭐⭐⭐⭐ (高级API) | ⭐⭐ (需手动管理) | | **返回值获取** | 直接通过 `result()` | 需队列传递 | | **资源管理** | 自动清理线程池 | 手动管理线程生命周期 | | **任务调度** | 内置线程池复用 | 需自行实现池管理 | | **推荐场景** | 大多数多线程任务 | 需要精细控制线程时 | ### 最佳实践建议 1. **优先使用 `concurrent.futures`**:语法简洁且自动管理线程池 2. **异常处理**:使用 `future.exception()` 捕获线程内异常 3. **超时控制**:`result(timeout=5)` 设置等待超时 4. **结果顺序**:`as_completed()` 按完成顺序获取结果: ```python for future in concurrent.futures.as_completed(futures): print(future.result()) ``` > 注意:Python 多线程受 GIL 限制,CPU 密集型任务建议使用 `ProcessPoolExecutor` 实现多进程行[^1][^2]。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值