进程池和线程池 concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor

本文通过实例演示了如何使用Python的线程池(ThreadPoolExecutor)和进程池(ProcessPoolExecutor)来执行任务。线程池部分展示了如何提交任务并获取结果,而进程池则使用了map方法来处理一组数据。

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

import time#线程池可以用shutdown submit

from threading import current_thread

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def f1(n):

  print(n)

  time.seelp(1)

  return n*n

if __name__ =="__main__":
  tp = ThreadPoolExecutor(4)

  lst = []

  for   i   in range(10):

    res = tp.submit(f1,i)

    lst.append(res)

  tp.shutdown()

  for i in lst:

    print(i.result())

 

import time#进程池  要用map

from threading import current_thread

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def f1(n):

  print(n)

  time.seelp(1)

  return n*n

if __name__ =="__main__":
  tp = ProcessPoolExecutor(4)

  res = tp.map(f1,rangr(10))

  print(res)

 

转载于:https://www.cnblogs.com/16795079a/p/10316321.html

<think>好的,用户现在想了解`concurrent.futures.ThreadPoolExecutor`的用法。之前用户的问题是关于如何调整代码,移除了对`results`的依赖,专注于执行任务处理异常。现在用户可能是在进一步学习并发编程,希望更深入地理解这个线程池的用法。 首先,我需要确定用户的基础。他们可能已经有一定的Python基础,但可能对并发编程不太熟悉,或者之前通过例子学习,现在想系统了解。需要从基础开始,但不要太过啰嗦,保持结构清晰。 用户的需求是了解ThreadPoolExecutor的用法,所以需要涵盖基本概念、核心方法、使用步骤、注意事项示例。同时,用户之前的代码涉及到异常处理文件操作,可能在多线程环境下需要注意线程安全资源竞争的问题,这也需要提到。 要确保回答结构清晰,分点说明,帮助用户逐步理解。可能还需要比较线程池进程池的区别,但用户现在只问ThreadPoolExecutor,所以重点在ThreadPoolExecutor上。 需要检查是否需要覆盖以下内容: 1. 什么是ThreadPoolExecutor,适用场景(I/O密集型任务)。 2. 核心方法:submit、map、shutdown。 3. 使用步骤:创建实例、提交任务、处理结果或异常。 4. 示例代码,比如网页抓取、文件处理等。 5. 注意事项,如GIL的影响,线程安全,资源释放,异常处理。 6.ProcessPoolExecutor的对比,帮助用户选择合适的执行器。 另外,用户之前的代码中使用了`as_completed`,所以需要解释这个方法的用途,以及为什么在处理任务结果时有用。可能还需要提到`future`对象的作用,以及如何通过它获取结果或异常。 要注意使用中文,避免使用复杂术语,必要时用例子辅助说明。比如,在解释submit返回future时,可以举一个简单的例子,如提交一个函数计算平方,然后通过future.result()获取结果。 还要注意用户可能的误区,比如认为多线程总能加速所有任务,需要指出适合I/O密集型而非CPU密集型。同时,提到资源管理,比如最大线程数的设置,避免过多线程导致的问题。 最后,确保示例代码符合用户之前的代码风格,比如使用logger记录错误,处理异常的方式。可能需要提供一个完整的例子,从导入模块到任务提交异常处理,让用户可以直接参考使用。 总结回答的结构: - 概述:定义、适用场景 - 核心方法:submit、map、shutdown - 使用步骤:创建、提交任务、处理结果 - 示例:多个例子,如网页请求、文件处理 - 注意事项:GIL、线程安全、异常处理 - 与ProcessPoolExecutor对比 - 总结:何时使用,最佳实践 需要确保每个部分简洁明了,重点突出。例如,在注意事项里,强调资源释放线程安全,因为用户之前的代码涉及文件生成,可能存在多线程写入同一文件的问题,需要提醒用户注意。 现在组织语言,确保逻辑连贯,分点清晰,用户能够一步步理解用法,并应用到实际项目中。</think>--- ### **`ThreadPoolExecutor` 核心作用** `concurrent.futures.ThreadPoolExecutor` 是 Python 标准库中实现**多线程并发**的工具,适用于 **I/O 密集型任务**(如网络请求、文件读写、数据库查询)。其核心优势是通过线程池管理,避免频繁创建/销毁线程的开销。 --- ### **核心方法解析** | 方法 | 用途 | 关键特性 | |---------------------|----------------------------------------------------------------------|-----------------------------------| | `.submit(fn, *args)` | 提交单个任务到线程池,返回 `Future` 对象 | 非阻塞,立即返回 | | `.map(fn, iterable)` | 批量提交任务,按输入顺序返回结果 | 简化循环提交,自动收集结果 | | `.shutdown()` | 关闭线程池,释放资源(通常用 `with` 语句自动管理) | 推荐用 `with` 上下文管理器替代 | --- ### **使用步骤与示例** #### **1. 基础用法:提交单个任务** ```python from concurrent.futures import ThreadPoolExecutor def task(n): return n * n with ThreadPoolExecutor(max_workers=3) as executor: future = executor.submit(task, 5) # 提交任务 result = future.result() # 阻塞等待结果 print(result) # 输出: 25 ``` #### **2. 批量处理:`map` 方法** ```python def download_url(url): # 模拟下载逻辑 return f"Downloaded: {url}" urls = ["https://example.com/1", "https://example.com/2"] with ThreadPoolExecutor() as executor: results = executor.map(download_url, urls) # 自动按顺序收集结果 for res in results: print(res) ``` #### **3. 动态任务管理:`as_completed`** ```python from concurrent.futures import as_completed def process_file(filename): # 模拟文件处理 if "error" in filename: raise ValueError("Invalid filename") return f"Processed: {filename}" files = ["data1.txt", "error.log", "data2.txt"] with ThreadPoolExecutor() as executor: futures = [executor.submit(process_file, f) for f in files] for future in as_completed(futures): # 按完成顺序处理 try: print(future.result()) except ValueError as e: print(f"任务失败: {e}") ``` --- ### **关键注意事项** 1. **GIL 限制** Python 的全局解释器锁(GIL)导致线程池**不适合 CPU 密集型任务**(如大量数学计算)。此时应改用 `ProcessPoolExecutor`。 2. **线程安全** - 避免多个线程同时修改**共享资源**(如全局变量、同一文件)。 - 若必须共享,需使用锁(`threading.Lock`)或线程安全数据结构(如 `queue.Queue`)。 3. **资源释放** - 确保任务函数正确关闭文件、数据库连接等资源,防止资源泄漏。 - 推荐使用 `with` 语句自动管理线程池生命周期。 4. **异常处理** - 必须显式调用 `future.result()` 才能捕获任务中的异常。 - 使用 `try-except` 包裹 `future.result()` 防止主程序崩溃。 --- ### **`ThreadPoolExecutor` vs `ProcessPoolExecutor`** | 特性 | `ThreadPoolExecutor` | `ProcessPoolExecutor` | |---------------------|-------------------------------|---------------------------------| | **适用场景** | I/O 密集型(网络、文件) | CPU 密集型(计算、数据处理) | | **资源开销** | 低(共享内存) | 高(独立内存空间) | | **数据传递** | 可直接传递对象(需注意线程安全)| 需序列化(`pickle`),速度较慢 | | **GIL 影响** | 受 GIL 限制 | 绕过 GIL,充分利用多核 | --- ### **最佳实践总结** 1. **合理设置 `max_workers`** - I/O 密集型任务:通常设置为 `5~10`(具体取决于外部系统响应速度)。 - 避免盲目增大线程数(可能引发资源竞争或系统限制)。 2. **优先使用 `with` 管理池生命周期** ```python with ThreadPoolExecutor() as executor: # 自动调用 shutdown() # 提交任务... ``` 3. **任务粒度控制** - 单个任务不宜过重(如处理超大文件),否则会阻塞线程池。 - 若任务复杂,可拆分为多个子任务并行。 4. **结果处理策略** - 需要顺序结果 → 用 `.map()` - 优先处理完成的任务 → 用 `as_completed()` --- ### **扩展场景示例:多线程文件写入** 若你的 `execute_query` 需生成独立文件(如按 `DRB_ID` 命名),可优化为: ```python def execute_query_optimized(sql, params): output_file = f"result_{params['DRB_ID']}.txt" # 唯一文件名 try: # 执行查询并写入文件 with open(output_file, "w") as f: f.write("查询结果数据...") except Exception as e: logger.error("写入文件 %s 失败: %s", output_file, e) ``` 此设计彻底避免多线程文件冲突,无需额外加锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值