python使用threading获取线程函数返回值的实现方法

本文介绍了一种在Python中使用threading模块获取线程函数返回值的方法。通过自定义多线程执行类MyThread,实现了对多个线程函数执行结果的汇总与判断。

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

python使用threading获取线程函数返回值的实现方法

这篇文章主要介绍了python使用threading获取线程函数返回值的实现方法,需要的朋友可以参考下

threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。python当前版本的多线程库没有实现优先级、线程组,线程也不能被停止、暂停、恢复、中断。

threading模块提供的类: 

  Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。

threading 模块提供的常用方法:

  threading.currentThread(): 返回当前的线程变量。

  threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。

  threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

threading 模块提供的常量:

  threading.TIMEOUT_MAX 设置threading全局超时时间。
好了,正文开始:

最近需要用python写一个环境搭建工具,多线程并行对环境各个部分执行一些操作,并最终知道这些并行执行的操作是否都执行成功了,也就是判断这些操作函数的返回值是否为0。但是threading并没有显式的提供获取各个线程函数返回值的方法,只好自己动手,下面就介绍一下自己的实现方式。

一开始考虑到执行的操作可能有很多,而且后续会不断补充,因此先写了一个通用的多线程执行类,封装线程操作的基本方法,如下:    
import threading
class MyThread(object):
  def __init__(self, func_list=None):
  #所有线程函数的返回值汇总,如果最后为0,说明全部成功
    self.ret_flag = 0
    self.func_list = func_list
    self.threads = []
  def set_thread_func_list(self, func_list):
    """
    @note: func_list是一个list,每个元素是一个dict,有func和args两个参数
    """
    self.func_list = func_list
  def start(self):
    """
    @note: 启动多线程执行,并阻塞到结束
    """
    self.threads = []
    self.ret_flag = 0
    for func_dict in self.func_list:
      if func_dict["args"]:
        t = threading.Thread(target=func_dict["func"], args=func_dict["args"])
      else:
        t = threading.Thread(target=func_dict["func"])
      self.threads.append(t)
    for thread_obj in self.threads:
      thread_obj.start()
    for thread_obj in self.threads:
      thread_obj.join()
  def ret_value(self):
    """
    @note: 所有线程函数的返回值之和,如果为0那么表示所有函数执行成功
    """
    return self.ret_flag

MyThread类会接受一个func_list参数,每个元素是一个dict,有func和args两个key,func是真正要执行的函数引用,args是函数的参数。其中最主要的方法是start方法,会多线程执行每个func,然后一直等到所有线程都执行结束后退出。接下来的关键就是如何对self.ret_flag设置正确的值,以判断所有的线程函数是否都返回0了。

我的实现是,在MyThread class中写一个方法trace_func,作为直接的线程函数,这个trace_func中执行真正需要执行的函数,从而可以获取到该函数的返回值,设置给self.ret_flag。

这个trace_func的第一参数是要执行的func引用,后面是这个func的参数,具体代码如下:    
def start(self):
  """
  @note: 启动多线程执行,并阻塞到结束
  """
  self.threads = []
  self.ret_flag = 0
  for func_dict in self.func_list:
    if func_dict["args"]:
      new_arg_list = []
      new_arg_list.append(func_dict["func"])
      for arg in func_dict["args"]:
        new_arg_list.append(arg)
      new_arg_tuple = tuple(new_arg_list)
      t = threading.Thread(target=self.trace_func, args=new_arg_tuple)
    else:
      t = threading.Thread(target=self.trace_func, args=(func_dict["func"],))
    self.threads.append(t)
  for thread_obj in self.threads:
    thread_obj.start()
  for thread_obj in self.threads:
    thread_obj.join()

这样能够成功获得返回值了,实验:    
def func1(ret_num):
  print "func1 ret:%d" % ret_num
  return ret_num
def func2(ret_num):
  print "func2 ret:%d" % ret_num
  return ret_num
def func3():
  print "func3 ret:100"
  return 100
mt = MyThread()
g_func_list = []
g_func_list.append({"func":func1,"args":(1,)})
g_func_list.append({"func":func2,"args":(2,)})
g_func_list.append({"func":func3,"args":None})
mt.set_thread_func_list(g_func_list)
mt.start()
print "all thread ret : %d" % mt.ret_flag

最后的输出结果
    
func1 ret:1
func2 ret:2
func3 ret:100
all thread ret : 103
总结
以上所述是小编给大家介绍的python使用threading获取线程函数返回值的实现方法,希望对大家有所帮助


数据分析师 Python

  CDA大数据分析圈是国内第一个汇聚大数据全面资源、数据人必备的APP。CDA整合了近千个大数据相关专业网站及媒体来源,汇聚了数百场国内大数据活动与会议,数千名名技术大牛、行业领袖,以及总结了最系统的优质学习课程资源。在这里,你可每天接触到最新行业资讯、前沿技术干货等信息;你可参与CDA俱乐部活动、各类大型会议,亲身与大牛接触,获得实务经验。你也可在专业课堂上与国内顶尖讲师进行交流切磋,最有效规划自身大数据职业发展。
  CDA大数据分析圈是数据人的家园,圈子里,资源流通,共享智慧,合作发展。CDA以“创新、开放、分享”的理念,期待你的加入!

转载于:https://www.cnblogs.com/amengduo/p/9586705.html

<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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值