Python 线程池/进程池 内存管理

深入理解进程与线程、进程池与线程池:企业级开发实战指南 程与线程是操作系统进行资源管理和任务执行的基本单位。进程拥有独立的地址空间,适合高隔离任务;线程共享进程资源,适合频繁切换或I/O密集型任务。线程池通过复用线程减少创建销毁开销,适合处理I/O密集型任务;进程池通过复用进程提供更高隔离性,适合处理计算密集型任务。 阅读详情

concurrent.futures 线程池/进程池内存管理

起因

之前进行爬虫任务的时候遇到了这么一个需求,1G 内存的机器跑爬虫,爬取一个网站的数据,之前使用的是这样一种方式:

 futures = list()
 with ThreadPool(max_workers=20) as exc:
      for tr in table.select("tr"):

          # 取线程执行结果
          future = exc.submit(self.get_asn, tr.strings)
          futures.append(future)

# 使用 as_completed 异步方式处理完成任务的线程
for future in as_completed(futures):
    result = future.result()
    # 拼接 asn.json 的 path
    file_path = result["asn"] + ".json"
    asn_file = os.path.join(self.base_data_path, file_path)

    with open(asn_file, "w", encoding="utf8") as f:
        f.write(json.dumps(result))

使用了 concurrent.futures 的 ThreadPoolExecutor submit 方法,因为开启了20个线程同时爬取,连接网站的速度还很快,任务很快就被处理完成了,可以看到我时完成一个任务的时候就进行写文件了操作,但是2分钟后很快程序就终止了,监控程序发现时由于程序内存占用达到 80% 被系统 Kill 掉了。

  • 为什么内存会爆呢?监控内存显示,程序处理完任务之后,内存并没有被立刻释放,而是有很长时间延迟之后才被释放( 在此吐槽 python GC)

改进方法:

参考 https://stackoverflow.com/questions/34770169/using-concurrent-futures-without-running-out-of-ram

# 允许同时进行的工作数
MAX_JOBS_IN_QUEUE = 1000


tr_list = table.select("tr")
tr_left = len(tr_list) - 1  # <----
tr_iter = iter(tr_list)  # <------
jobs = dict()

  with ThreadPool(max_workers=20) as exc:
      while tr_left:
          print("#" * 100, "TASK: {} <===>  JOB: {}".format(tr_left, len(jobs)))
          for tr in tr_iter:
              # 取线程执行结果
              job = exc.submit(self.get_asn, tr.strings)
              jobs[job] = tr
              if len(jobs) > MAX_JOBS_IN_QUEUE:
                  break  # limit the job submission for now job

          # 使用 as_completed 异步方式处理任务线程
          for job in as_completed(jobs):
              tr_left -= 1  # one down - many to go...   <---
              result = job.result()
              # 从字典中删除结果,因为我们不需要存储它
              del jobs[job]

              # 拼接 asn.json 的 path
              file_path = result["asn"] + ".json"
              asn_file = os.path.join(self.base_data_path, file_path)

              with open(asn_file, "w", encoding="utf8") as f:
                  f.write(json.dumps(result))
              break

改进后内存在切换 html 爬取的时候,会偶尔会升高一下,最高 65%,平均在 35% 左右。

  • ProcessPoolExecutor 进程同理
Python的线程池实现 NULL 博文链接:https://biansutao.iteye.com/blog/377402 立即下载

相关推荐

VMware 虚拟机里连不上网的五种解决方案

在VMware虚拟机里的虚拟机系统连接不上网络 首先,注意查看适配器选项里的网络连接这两个网络连接是否存在,如果不存在可以重新装一下VM 如果存在,连不上网 解决办法一: 虚拟机设置里,找到“网络适配器”,右边的网络连接选择“NAT 模式”,如果不行的话再linux系统。还是不行的话接着看第二种解决方案。 解决方法二: 可能原因是VMware NET Service...

墨轩 18万+

第17章:使用 concurrent.futures 模块处理并发-使用 futures.as_completed 函数立刻获取多线程任务执行结果

前面的章节我们使用了Executor.map 函数,这个函数易于使用,不过有个特性可能有用,也可能没用, 具体情况取决于需求:这个函数返回结果的顺序与调用开始的顺序一致。 我们知道map 返回的结果是一个生成器 results,当我们用 for 循环取值时, for 会隐式调用 next(results) 返回第一个任务,然后又会在第一个任务的 Future实例上调用 .result() 方法。而 result() 方法会阻塞,直到第一个Future 运行结束;如果第一个调用生成结果用时 10 秒...

waitan2018的博客 5564

平衡电桥检测高压绝缘电阻的原理

检测绝缘漏电的高压拓扑如下:BMU需要连接BAT+,BAT-和PE线,并测量电池总压(Ubatt)和负母线电压(Un),并计算出正母线电压(Up)。

booksyhay的专栏 1万+

python3 sleep 并发_Python3 并发 | concurrent.futures

# -*- coding: utf-8 -*-from concurrent.futures import ThreadPoolExecutor, wait, as_completed, ALL_COMPLETEDimport loggingimport randomimport queueimport timelogger = logging.getLogger()logger.setLevel...

weixin_33391446的博客 174

AD9361数字调制入门:从IQ调制原理到动手实现第一个ASK信号(Vivado工程详解)

本文详细介绍了如何使用AD9361射频收发器实现ASK数字调制,从IQ调制原理到Vivado工程实现。通过Verilog代码示例和FPGA架构设计,帮助开发者理解纯逻辑实现数字调制解调的关键技术,特别适合软件无线电(SDR)初学者入门实践。

weixin_29158047的博客 374

UE4初学笔记_02_编辑器界面

不同版本可能不一样,这里是4.25 UE4编辑器主界面(也称为关卡编辑器)主要用于构建世界场景和关卡以及放置资源。 1.菜单栏 2.关卡编辑器(Level Editor)工具栏 3.“模式”(Modes)面板 4.“内容浏览器”(Content Browser)面板 5.“视口”(Viewport)面板 6.“世界大纲视图”(World Outliner)面板 7.“细节”(Details)面板 1.菜单栏 菜单栏包含“文件”(File) 、“编辑”(Edit) 、“窗口”(Win.

来自火星的猫 3092

Python学习:垃圾回收机制

Python 程序在运行的时候,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量;计算完成后,再将结果输出到永久性存储器中。如果数据量过大,内存空间管理不善就很容易出现 OOM(out of memory),俗称爆内存,程序可能被操作系统中止。 而对于服务器,这种设计为永不中断的系统来说,内存管理则显得更为重要,不然很容易引发内存泄漏。什么是内存泄漏呢? 这里的泄漏,并不是说你的内存出现了信息安全问题,被恶意程序利用了,而是指程序本身没有设计好,导致程序未能释放已不再使用的内存。 内存泄漏也不是指

小朱小朱绝不认输的博客 2554

SpringBoot3 + Vben5.0实战:从零搭建企业级管理后台(附完整代码)

本文详细介绍了如何从零开始,使用SpringBoot3与Vben5.0技术栈搭建现代化企业级管理后台。通过对比分析,阐述了该组合在开发效率、性能(如虚拟线程)和权限模型(RBAC)方面的优势,并提供了从项目初始化、核心功能开发到部署运维的完整实战指南,帮助开发者快速构建高性能、易维护的后台系统。

weixin_29306317的博客 171

高效处理大规模数据:使用 Python 进行内存优化和并行计算

高效处理大规模数据不仅仅依赖于强大的硬件资源,还需要通过合理的编程技巧和技术来优化内存使用和加速计算。通过利用 Python 的内存优化技术、生成器、NumPy/Pandas 的高效数据结构,以及多线程、多进程和异步编程等并行计算方法,开发者能够在处理大数据时获得显著的性能提升。这些技术可以帮助你在开发中更好地应对大规模数据处理的挑战,无论是在数据分析、机器学习模型训练,还是在日常的业务数据处理任务中,都能提供巨大的帮助。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1363

TypeScript的安装与使用

TypeScript的安装与使用

qq_51589308的博客 600

关于 Nginx 监听地址 0.0.0.0 的详细解释

0.0.0.0在Nginx配置中表示监听服务器所有网络接口(包括公网IP、内网IP和本地回环地址),这是默认配置。当使用listen 80;时,Nginx会接受通过服务器任何IP地址的80端口访问请求。相比只监听特定IP,这种配置更通用,但也意味着服务会对外网开放,需注意安全风险。可通过netstat命令验证监听状态,显示0.0.0.0:80即表示正确配置。

weixin_43674738的博客 1563

python processpoolexecutor_python线程池ThreadPoolExecutor与进程池ProcessPoolExecutor

python中ThreadPoolExecutor(线程池)与ProcessPoolExecutor(进程池)都是concurrent.futures模块下的,主线程(或进程)中可以获取某一个线程(进程)执行的状态或者某一个任务执行的状态及返回值。通过submit返回的是一个future对象,它是一个未来可期的对象,通过它可以获悉线程的状态ThreadPoolExecutor(线程池)通过subm...

weixin_39553600的博客 486

windows中通过docker部署LocateAnything-3B模型

windows中通过docker部署LocateAnything-3B模型

yilvyangguang520的博客 483

DECO安全与最佳实践:确保并行程序稳定运行的10个关键要点

DECO是一个专注于并发编程的装饰器工具,通过简洁的API帮助开发者轻松实现多线程和多进程任务处理。本文将分享确保DECO并行程序稳定运行的10个关键安全要点与最佳实践,帮助新手开发者避免常见的并发陷阱。 ## 1. 选择合适的并发模型 DECO提供了线程池(ThreadPool)和进程池(Pool)两种并发模型,需要根据任务特性选择: - CPU密集型任务优先使用`multiprocessi

gitblog_00224的博客 614

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Pixel Dimension Fissioner 企业级应用:Java微服务集成与高可用部署

本文介绍了如何在星图GPU平台上自动化部署🕹️ 像素语言 · 维度裂变器 (Pixel Dimension Fissioner)镜像,实现企业级Java微服务集成与高可用部署。该方案特别适用于电商平台的大规模图片处理场景,如商品主图生成,通过SpringBoot封装和Kubernetes部署,可稳定处理百万级QPS,显著提升系统可靠性和扩展性。

weixin_34535286的博客 328

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python GIL锁、进程池与线程池、同步异步

一、GIL全局解释器锁 全局解释器锁 在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本机线程同时执行Python代码。之所以需要这个锁,主要是因为CPython的内存管理不是线程安全的。(然而,自从GIL存在以来,其他特性已经逐渐依赖于它所执行的保证) 什么是GIL 全局解释器锁, 施加在解释器上的互斥锁 为什么需要GIL 由于CPyth...

weixin_34268843的博客 172

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

python 进程池阻塞和非阻塞_Python Day 37:GIL锁/进程池/线程池/阻塞与非阻塞/同步与异步/异步回调/...

## GIL锁:```python官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiplenative threads from executing Python bytecodes at once. This lock is necessary mainlybecause ...

weixin_39898550的博客 370

CIL锁,GIL与线程池的区别,进程池和线程池,同步与异步

一.GIL锁 什么是GIL? 全局解释器锁,是加在解释器上的互斥锁 GC是python自带的内存管理机制,GC的工作原理:python中的内存管理使用的是应用计数,每个数会被加上一个整型的计数器,表示这个数据被引用的次数,当这个整数变为0时则表示该数据已经没有人使用,成为了垃圾数据,当内存占用达到某个阈值,GC会将其他线程挂起,然后执行垃圾清理操作,垃圾清理也是一串代码,也就需要一条线程来执行...

weixin_30482383的博客 244

GIL锁、进程池与线程池

1.什么是GIL? 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly be...

weixin_30906425的博客 220

Python Day 37:GIL锁/进程池/线程池/阻塞与非阻塞/同步与异步/异步回调/

## GIL锁: ```python 官方解释: ''' In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is nec...

weixin_30367169的博客 161

并发编程:GIL,线程池,进程池,阻塞,非阻塞,同步,异步

一 GIL(global interpreter lock) GIL中文叫全局解释器锁,我们执行一个文件会产生一个进程,那么我们知道进程不是真正的执行单位,而是资源单位,所以进程中放有解释器(cpython)和py文件,也就是解释器需要解释的文件,即CPU要运行的文件。 GIL: GIL本质上是一个互斥锁,是一个加在解释器身上的互斥锁, 在同一个进程内,所有的线程要想执...

ancan7211的博客 153

GIL 进程池与线程池

一.全局解释器锁   1.GIL:全局解释器锁     GIL本质就是一把互斥锁,是夹在解释器身上的     统一进程内的所有线程都需要先抢到GIL锁,才能执行pai解释器代码   2.GIL优缺点:     优点:       保证Cpython解释器内存管理的线程安全     缺点:       同一进程内所有的线程同一时刻只能有一个执行,       也就是锁Cp...

dkxy35121的博客 155

python-GIL锁-多线程与多进程效率对比-进程池和线程池的使用-同步与异步

文章目录一、GIL锁二、多线程与多进程效率对比三、GIL与自定义线程锁的区别四、进程池和线程池的使用五、同步与异步 一、GIL锁 什么是GIL:全局解释器锁,是加在解释器上的互斥锁 为什么需要GIL:由于CPython的内存管理是非线程安全,于是CPython就给解释器加了个锁,解决了安全问题 ,但是降低了效率。另外,虽然有解决方案,但是由于牵涉太多,一但修改则很多以前基于GIL的程序都需...

zdc45625的博客 592

并发编程: GIL锁、GIL与互斥锁区别、进程池与线程池的区别

一、GIL 二、关于GIL性能的讨论 三、计算密集测试 四、IO密集测试 五、GIL与互斥锁 六、TCP客户端 七、进程池 八、进程什么时候算是空闲 九、线程池 一、GIL GIL Global Interpreter Lock 全局解释器锁 锁就是线程里面那个锁 锁是为了避免资源竞争造成数据的错乱 python程序的执行过程 ...

weixin_30379973的博客 129

这大概是你见过最全面的 Python 重点了

来源:二十一 链接:https://segmentfault.com/a/1190000018737045公众号「小詹学Python」后台回复「1024」领取超值关注大礼包!由于总结了太多的东西,所以篇幅有点长,这也是我"缝缝补补"总结了好久的东西。Py2 VS Py3print成为了函数,python2是关键字不再有unicode对象,默认str就是unicodepython3除号返回浮点...

小詹学python的博客 221
上一篇: CentOS7 安装 MongoDB3.6
下一篇: go语言笔记——切片底层本质是共享数组内存!!!绝对不要用指针指向 slice切片本身已经是一个引用类型就是指针
SmallTankPy
博客等级 码龄10年 26粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值