You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python处理地址匹配时的exit code 137错误?

解决地址匹配时的内存不足(SIGKILL)问题

你遇到的exit code 137确实是内存耗尽导致系统强制终止进程。核心问题出在两个关键环节:

  • 虽然用Dask读取了300万条的business_rates.csv,但list(df.address)直接把所有地址全量加载到内存,完全浪费了Dask的分块优势
  • process.cdist对1000条参考地址和300万条主地址计算相似度矩阵,会生成1000×300万的巨型数组,光是存储这个数组就需要几十GB内存,直接撑爆内存

下面是针对性的优化方案:

1. 先按邮编缩小匹配范围(最有效)

地址匹配时,相同邮编的地址才具备匹配可能,先按邮编过滤能把匹配范围缩小几个数量级:

  • 给主数据和参考数据都提取并标准化邮编(统一大小写、去除空格)
  • 按邮编分组,只在同一邮编组内做地址相似度匹配

2. 不要一次性加载全量主数据到内存

用Pandas分块读取主数据,每次只处理一小块,或者用Dask的分块特性并行处理:

import pandas as pd
from rapidfuzz import process, fuzz
import time

# 读取参考数据并按邮编分组
ref_df = pd.read_csv('all_food_hygiene_data_clean_up.csv')
ref_df['post_code_clean'] = ref_df['post_code'].str.strip().str.upper()
ref_groups = ref_df.groupby('post_code_clean')

# 分块读取主数据,每次处理10万条
chunk_size = 100000
results = []

start = time.time()
print("start time:", time.ctime(start))

for chunk in pd.read_csv('business_rates.csv', chunksize=chunk_size, low_memory=False):
    # 从主地址中提取并标准化邮编
    chunk['post_code_clean'] = chunk['address'].str.extract(r'([A-Z]{1,2}[0-9][A-Z0-9]? ?[0-9][A-Z]{2})', expand=False)
    chunk['post_code_clean'] = chunk['post_code_clean'].str.strip().str.upper()
    
    # 遍历每个邮编组,只在同邮编内做匹配
    for post_code, ref_group in ref_groups:
        if post_code not in chunk['post_code_clean'].unique():
            continue
        
        # 提取当前邮编下的主地址和参考地址
        chunk_addresses = chunk[chunk['post_code_clean'] == post_code]['address'].tolist()
        ref_addresses = ref_group['ref_address'].unique().tolist()
        
        # 批量匹配,只保留最高分结果
        for ref_addr in ref_addresses:
            matches = process.extractOne(ref_addr, chunk_addresses, scorer=fuzz.token_sort_ratio, score_cutoff=70)
            if matches:
                results.append({
                    'ref_address': ref_addr,
                    'matched_address': matches[0],
                    'score': matches[1],
                    'post_code': post_code
                })

# 合并结果并保存
results_df = pd.DataFrame(results)
final_df = pd.merge(ref_df, results_df, how='left', on='ref_address')
final_df.to_csv('results.csv', index=False)

end = time.time()
print("end time:", time.ctime(end))

3. 优化RapidFuzz计算参数

  • 提高score_cutoff的值(比如70),过滤低匹配分的结果,减少计算量和内存占用
  • 不要用workers=-1,限制线程数避免内存竞争
  • 用process.extractOne代替cdist,只获取每个参考地址的最高分匹配,不需要生成全量相似度矩阵

4. 用Dask实现并行处理

如果需要处理全量数据,可利用Dask的map_partitions并行处理每个分区:

import dask.dataframe as dd
from rapidfuzz import process, fuzz

def match_partition(partition, ref_addresses):
    matches = []
    for addr in partition['address']:
        best_match = process.extractOne(addr, ref_addresses, scorer=fuzz.token_sort_ratio, score_cutoff=70)
        if best_match:
            matches.append({
                'original_address': addr,
                'matched_ref_address': best_match[0],
                'score': best_match[1]
            })
    return pd.DataFrame(matches)

# 读取数据
ref_df = pd.read_csv('all_food_hygiene_data_clean_up.csv')
ref_addresses = ref_df['ref_address'].unique().tolist()
df = dd.read_csv('business_rates.csv', low_memory=False)

# 并行处理每个分区
matches_df = df.map_partitions(match_partition, ref_addresses, meta={
    'original_address': str,
    'matched_ref_address': str,
    'score': float
})

# 保存结果
matches_df.compute().to_csv('dask_matches.csv', index=False)

关键注意点

  • 永远不要把大Dask DataFrame转成list或Pandas DataFrame,这会把全量数据加载到内存
  • 地址匹配前先做数据清洗:统一大小写、去除多余空格、标准化街道名称(比如把"St."改成"Street"),能提高匹配准确率和速度
  • 如果内存仍然紧张,可以考虑增加机器内存,或者使用高内存云服务器实例

内容的提问来源于stack exchange,提问作者Kelly Tang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:30:57