如何在Python中高效读取CSV文件以提取2020年香港新冠疫情数据
现有方案的性能瓶颈
你当前方案耗时高的核心原因有两个:
- 每次调用
pd.read_csv都会把整个包含全球所有地区数据的CSV全量加载到内存,实际上你只需要香港对应的1行数据,99%的IO和内存开销都是冗余的 - 串行读取345个文件,全程等待网络IO返回,CPU全程处于闲置状态,资源利用率极低
优化思路
- 读文件阶段就做行过滤:用原生CSV模块逐行读取,匹配到香港的行之后直接终止当前文件读取,不用读完整个文件,IO开销直接降低两个数量级
- 用多线程并发读取:文件读取是典型的IO密集型任务,多线程可以充分利用网络等待的空窗时间,不用串行排队等每个文件返回
- 合并逻辑优化:所有筛选结果攒齐后一次性合并,避免逐次append产生的冗余数据复制
优化实现代码
import pandas as pd import csv from concurrent.futures import ThreadPoolExecutor, as_completed # 统一列名映射和需要保留的字段 COLUMN_MAPPING = { "Province_State": "Province/State", "Country_Region": "Country/Region", "Last_Update": "Last Update" } REQUIRED_COLS = ["Province/State", "Country/Region", "Last Update", "Confirmed", "Deaths", "Recovered"] def get_hk_row(url): # 遇到编码问题可在get_handle参数中加 encoding="utf-8" 或 "latin-1" with pd.io.common.get_handle(url, 'r') as f: reader = csv.DictReader(f) for row in reader: # 兼容两种字段名的格式 province = row.get("Province/State") or row.get("Province_State") if province == "Hong Kong": temp_df = pd.DataFrame([row]) # 统一列名 temp_df = temp_df.rename(columns=COLUMN_MAPPING) # 补全缺失字段、统一格式 for col in REQUIRED_COLS: if col not in temp_df.columns: temp_df[col] = None temp_df = temp_df[REQUIRED_COLS] # 数值字段转类型 for num_col in ["Confirmed", "Deaths", "Recovered"]: temp_df[num_col] = pd.to_numeric(temp_df[num_col], errors="coerce") return temp_df return pd.DataFrame(columns=REQUIRED_COLS) # 多线程并发处理所有CSV链接 result_list = [] # max_workers可以根据你的网络情况调整,10-20都可以 with ThreadPoolExecutor(max_workers=15) as pool: tasks = [pool.submit(get_hk_row, url) for url in hrefs] for task in as_completed(tasks): res = task.result() if not res.empty: result_list.append(res) # 一次性合并所有结果 final_df = pd.concat(result_list, ignore_index=True)
额外优化建议
如果这是需要重复执行的任务,可以把第一次爬取到的香港数据落地成本地缓存文件,后续运行直接读本地文件,不需要重新请求所有CSV。
内容的提问来源于stack exchange,提问作者YIMING ZHAO
相关产品推荐
相关产品推荐

