
Python通过future处理并发问题
future初识
通过下面脚本来对future进行一个初步了解:
例子1:普通通过循环的方式
import os
import time
import sys
import requests
POP20_CC = (
"CN IN US ID BR PK NG BD RU JP MX PH VN ET EG DE IR TR CD FR"
).split()
BASE_URL = 'http://flupy.org/data/flags'
DEST_DIR = 'downloads/'
def save_flag(img,filename):
path = os.path.join(DEST_DIR,filename)
with open(path,'wb') as fp:
fp.write(img)
def get_flag(cc):
url = "{}/{cc}/{cc}.gif".format(BASE_URL,cc=cc.lower())
resp = requests.get(url)
return resp.content
def show(text):
print(text,end=" ")
sys.stdout.flush()
def download_many(cc_list):
for cc in sorted(cc_list):
image = get_flag(cc)
show(cc)
save_flag(image,cc.lower()+".gif")
return len(cc_list)
def main(download_many):
t0 = time.time()
count = download_many(POP20_CC)
elapsed = time.time()-t0
msg = "\n{} flags downloaded in {:.2f}s"
print(msg.format(count,elapsed))
if __name__ == '__main__':
main(download_many)
例子2:通过future方式实现,这里对上面的部分代码进行了复用
from concurrent import futures
from flags import save_flag, get_flag, show, main
MAX_WORKERS = 20
def download_one(cc):
image = get_flag(cc)
show(cc)
save_flag(image, cc.lower()+".gif")
return cc
def download_many(cc_list):
workers = min(MAX_WORKERS,len(cc_list))
with futures.ThreadPoolExecutor(workers) as executor:
res = executor.map(download_one, sorted(cc_list))
return len(list(res))
if __name__ == '__main__':
main(download_many)
分别运行三次,两者的平均速度:13.67和1.59s,可以看到差别还是非常大的。
future
future是concurrent.futures模块和asyncio模块的重要组件
从python3.4开始标准库中有两个名为Future的类:concurrent.futures.Future和asyncio.Future
这两个类的作用相同:两个Future类的实例都表示可能完成或者尚未完成的延迟计算。与Twisted中的Deferred类、Tornado框架中的Future类的功能类似
注意:通常情况下自己不应该创建future,而是由并发框架(concurrent.futures或asyncio)实例化
原因:future表示终将发生的事情,而确定某件事情会发生的唯一方式是执行的时间已经安排好,因此只有把某件事情交给concurrent.futures.Executor子类处理时,才会创建concurrent.futures.Future实例。
如:Executor.submit()方法的参数是一个可调用的对象,调用这个方法后会为传入的可调用对象排定时间,并返回一个
future
客户端代码不能应该改变future的状态,并发框架在future表示的延迟计算结束后会改变期物的状态,我们无法控制计算何时结束。
这两种future都有.done()方法,这个方法不阻塞,返回值是布尔值,指明future链接的可调用对象是否已经执行。客户端代码通常不会询问future是否运行结束,而是会等待通知。因此两个Future类都有.add_done_callback()方法,这个方法只有一个参数,类型是可调用的对象,future运行结束后会调用指定的可调用对象。
.result()方法是在两个Future类中的作用相同:返回可调用对象的结果,或者重新抛出执行可调用的对象时抛出的异常。但是如果future没有运行结束,result方法在两个Futrue类中的行为差别非常大。
对concurrent.futures.Future实例来说,调用.result()方法会阻塞调用方所在的线程,直到有结果可返回,此时,result方法可以接收可选的timeout参数,如果在指定的时间内future没有运行完毕,会抛出TimeoutError异常。
而asyncio.Future.result方法不支持设定超时时间,在获取future结果最好使用yield from结构,但是concurrent.futures.Future不能这样做
不管是asyncio还是concurrent.futures.Future都会有几个函数是返回future,其他函数则是使用future,在最开始的例子中我们使用的Executor.map就是在使用future,返回值是一个迭代器,迭代器的__next__方法调用各个future的result方法,因此我们得到的是各个futrue的结果,而不是future本身
关于future.as_completed函数的使用,这里我们用了两个循环,一个用于创建并排定future,另外一个用于获取future的结果
结果如下:
注意:Python代码是无法控制GIL,标准库中所有执行阻塞型IO操作的函数,在等待操作系统返回结果时都会释放GIL.运行其他线程执行,也正是因为这样,Python线程可以在IO密集型应用中发挥作用
以上都是concurrent.futures启动线程,下面通过它启动进程
concurrent.futures启动进程
concurrent.futures中的ProcessPoolExecutor类把工作分配给多个Python进程处理,因此,如果需要做CPU密集型处理,使用这个模块能绕开GIL,利用所有的CPU核心。
其原理是一个ProcessPoolExecutor创建了N个独立的Python解释器,N是系统上面可用的CPU核数。
使用方法和ThreadPoolExecutor方法一样
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
机器学习解决实际问题的核心关键:从业务到落地的全流程解析 在人工智能技术落地的浪潮中,机器学习作为核心工具,已广泛应用于 ...
2025-09-09SPSS 编码状态区域中 Unicode 的功能与价值解析 在 SPSS(Statistical Product and Service Solutions,统计产品与服务解决方案 ...
2025-09-09CDA 数据分析师:驾驭商业数据分析流程的核心力量 在商业决策从 “经验驱动” 向 “数据驱动” 转型的过程中,商业数据分析总体 ...
2025-09-09R 语言:数据科学与科研领域的核心工具及优势解析 一、引言 在数据驱动决策的时代,无论是科研人员验证实验假设(如前文中的 T ...
2025-09-08T 检验在假设检验中的应用与实践 一、引言 在科研数据分析、医学实验验证、经济指标对比等领域,常常需要判断 “样本间的差异是 ...
2025-09-08在商业竞争日益激烈的当下,“用数据说话” 已从企业的 “加分项” 变为 “生存必需”。然而,零散的数据分析无法持续为业务赋能 ...
2025-09-08随机森林算法的核心特点:原理、优势与应用解析 在机器学习领域,随机森林(Random Forest)作为集成学习(Ensemble Learning) ...
2025-09-05Excel 区域名定义:从基础到进阶的高效应用指南 在 Excel 数据处理中,频繁引用单元格区域(如A2:A100、B3:D20)不仅容易出错, ...
2025-09-05CDA 数据分析师:以六大分析方法构建数据驱动业务的核心能力 在数据驱动决策成为企业共识的当下,CDA(Certified Data Analyst) ...
2025-09-05SQL 日期截取:从基础方法到业务实战的全维度解析 在数据处理与业务分析中,日期数据是连接 “业务行为” 与 “时间维度” 的核 ...
2025-09-04在卷积神经网络(CNN)的发展历程中,解决 “梯度消失”“特征复用不足”“模型参数冗余” 一直是核心命题。2017 年提出的密集连 ...
2025-09-04CDA 数据分析师:驾驭数据范式,释放数据价值 在数字化转型浪潮席卷全球的当下,数据已成为企业核心生产要素。而 CDA(Certified ...
2025-09-04K-Means 聚类:无监督学习中数据分群的核心算法 在数据分析领域,当我们面对海量无标签数据(如用户行为记录、商品属性数据、图 ...
2025-09-03特征值、特征向量与主成分:数据降维背后的线性代数逻辑 在机器学习、数据分析与信号处理领域,“降维” 是破解高维数据复杂性的 ...
2025-09-03CDA 数据分析师与数据分析:解锁数据价值的关键 在数字经济高速发展的今天,数据已成为企业核心资产与社会发展的重要驱动力。无 ...
2025-09-03解析 loss.backward ():深度学习中梯度汇总与同步的自动触发核心 在深度学习模型训练流程中,loss.backward()是连接 “前向计算 ...
2025-09-02要解答 “画 K-S 图时横轴是等距还是等频” 的问题,需先明确 K-S 图的核心用途(检验样本分布与理论分布的一致性),再结合横轴 ...
2025-09-02CDA 数据分析师:助力企业破解数据需求与数据分析需求难题 在数字化浪潮席卷全球的当下,数据已成为企业核心战略资产。无论是市 ...
2025-09-02Power BI 度量值实战:基于每月收入与税金占比计算累计税金分摊金额 在企业财务分析中,税金分摊是成本核算与利润统计的核心环节 ...
2025-09-01巧用 ALTER TABLE rent ADD INDEX:租房系统数据库性能优化实践 在租房管理系统中,rent表是核心业务表之一,通常存储租赁订单信 ...
2025-09-01