如何使用Pyrosm处理超大OSM数据(.osm.pbf文件)
处理Pyrosm解析超大OSM PBF文件的内存问题
一、类似Pandas分块的处理方案
Pyrosm本身支持分块读取逻辑,无需拆分原始文件即可逐步处理数据,核心思路是按地理区域或要素类型拆分读取:
按地理区块分块读取
先获取目标文件的整体边界,再拆分为多个子边界框,逐个读取并处理:from pyrosm import OSM # 初始化OSM对象 osm = OSM("large_file.osm.pbf") # 获取文件覆盖的整体边界 bounds = osm.get_bounds() # 拆分边界为4个区块(可根据内存情况调整拆分粒度) x_mid = (bounds["minlon"] + bounds["maxlon"]) / 2 y_mid = (bounds["minlat"] + bounds["maxlat"]) / 2 bboxes = [ (bounds["minlon"], bounds["minlat"], x_mid, y_mid), (x_mid, bounds["minlat"], bounds["maxlon"], y_mid), (bounds["minlon"], y_mid, x_mid, bounds["maxlat"]), (x_mid, y_mid, bounds["maxlon"], bounds["maxlat"]) ] # 逐个处理区块 for idx, bbox in enumerate(bboxes): # 读取当前区块的道路数据(可替换为建筑、POI等其他要素) roads = osm.get_network(nodes=False, bounding_box=bbox) # 执行自定义处理逻辑,比如保存到本地文件 roads.to_parquet(f"roads_chunk_{idx}.parquet") # 手动释放内存 del roads按要素类型分批读取
避免一次性加载所有要素类型,分开读取并处理不同类别数据:osm = OSM("large_file.osm.pbf") # 先处理道路网络 roads = osm.get_network() roads.to_parquet("roads_full.parquet") del roads # 再处理建筑数据 buildings = osm.get_buildings() buildings.to_parquet("buildings_full.parquet") del buildings # 最后处理POI数据 pois = osm.get_pois() pois.to_parquet("pois_full.parquet") del pois
二、拆分OSM PBF文件的方法
如果分块读取仍无法解决内存问题,可以先拆分原始文件,再分别处理。常用工具是osmium-tool(轻量级命令行工具):
1. 安装osmium-tool
- Linux:通过包管理器安装,如
apt install osmium-tool - macOS:使用Homebrew安装,
brew install osmium-tool - Windows:直接搜索下载预编译二进制文件
2. 按边界框拆分
# 提取指定边界框内的区域到新文件 osmium extract --bbox minlon,minlat,maxlon,maxlat large_file.osm.pbf -o chunk1.osm.pbf
3. 按行政区域拆分
如果有目标行政区域的.poly边界文件,可基于此拆分:
osmium extract --polygon city_boundary.poly large_file.osm.pbf -o city_chunk.osm.pbf
4. 按文件大小拆分
仅按文件体积拆分(不保证地理连续性):
# 拆分每个文件块为500MB osmium split --size 500M large_file.osm.pbf
注意事项
- 分块读取时,需注意处理跨区块的重复要素,可在最终合并时去重。
- 使用
osmium-tool拆分时,尽量保留元数据,避免后续解析异常。 - 处理完每个区块/文件后,可手动触发垃圾回收(
import gc; gc.collect())进一步释放内存。
内容的提问来源于stack exchange,提问作者Lupos
相关产品推荐
相关产品推荐

