本章主要讨论 Python 3.2 引入的 concurrent.futures 模块。这一章还会介绍“Future”的概念,Future 指一种对象,表示异步执行的操作。这个概念的作用很大,是 concurrent.futures 模块和 asyncio 包的基础。
17.1 使用 concurrent.futures 模块并发处理下载任务
为了高效处理网络 I/O,需要使用并发,因为网络有很高的延迟,所以为了不浪费 CPU 周期去等待,最好在收到网络响应之前做些其他的事。为了说明这一点,我们通过代码来示例:
示例 17-1-1 普通批量下载:依次循环从网上下载 20 个国家的国旗图像:
# 可以从输出结果中看到,下载 20 个国旗图片共计用时 15.41s,示例中没有什么新知识,只是与其他脚本对比的基准;
import os
import sys
import time
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'
# 保存地址
DOWN_DIR = 'downloads/'
def download_flag(cc):
"""下载国旗"""
# 图片地址
url = f'{BASE_URL}/{cc.lower()}/{cc.lower()}.gif'
image = requests.get(url).content
# 下载完成打印出国家
print(cc, end=' ')
# 刷新控制台
sys.stdout.flush()
# 保存图片
path = os.path.join(DOWN_DIR, cc + '.gif')
with open(path, 'wb') as fp:
fp.write(image)
# 返回国家简称
return cc
def batch_downloads():
"""批量下载"""
down_list = []
for country in sorted(POP20_CC):
cc = download_flag(country)
down_list.append(cc)
return down_list
def main():
"""开始下载并计算下载所需时间"""
start_time = time.tim