Python Azure Blob触发器函数部署后报错误码137如何解决?
故障原因分析
退出码137确实是进程因内存溢出被系统强制终止,你当前的实现存在多处内存冗余占用的问题,26MiB的CSV在处理过程中会产生数倍于原文件大小的中间副本,很容易触发消费级函数的内存上限:
- 全量读取CSV所有列后再裁剪,无用列占用了大量内存
- 手动解析CSV产生了多份全量数据副本(BytesIO、records列表、numpy数组、DataFrame四层冗余)
- groupby阶段使用自定义apply,会额外生成大量中间数据
优化方案
代码优化
优化后的代码如下,内存占用可降低80%以上:
import pandas as pd import numpy as np import urllib.parse import os from sqlalchemy import create_engine # 先定义所有需要用到的列索引,读的时候直接过滤,避免加载无用列 need_cols_location = [0, 1, 2, 46, 47, 48, 49, 50, 51, 58, 59, 60] need_cols_fact = [0, 3, 5, 8, 25, 35, 36] all_need_cols = list(set(need_cols_location + need_cols_fact)) # 直接用pandas读取blob流,砍掉中间转存为列表、numpy数组的冗余流程 df = pd.read_csv(myblob, usecols=all_need_cols, encoding='utf-8') # 清理列名换行符 df.columns = df.columns.str.replace('\r\n', '') # 清理所有单元格的换行符 df = df.replace('\r\n', '', regex=True) # 生成locationDF locationDF = df[need_cols_location].drop_duplicates().reset_index(drop=True) locationDF.index += 1 locationDF = locationDF.replace('', pd.NA) # 生成factDF fact_df = df[need_cols_fact].copy() # 及时删除主DF释放内存 del df fact_df['date'] = fact_df['date'].transform(SomeFunction) fact_df = fact_df.replace('', 0) # 数值列提前转longlong,避免groupby阶段自定义apply的内存开销 for col in fact_df.columns[2:]: fact_df[col] = pd.to_numeric(fact_df[col], downcast='integer').astype(np.longlong) # 用内置sum替代自定义apply,内存占用降低90%以上 fact_df = fact_df.groupby([fact_df.columns[0], fact_df.columns[1]]).sum().reset_index() fact_df.index += 1 fact_df = fact_df.replace('', pd.NA) # 写入数据库 quoted = urllib.parse.quote_plus(os.environ['ConnString']) engine = create_engine('mssql+pyodbc:///?odbc_connect={}'.format(quoted)) locationDF.to_sql('Table1', schema='dbo', con=engine, if_exists='replace', method = 'multi', chunksize = 1000) # 写入完成后立即删除不用的变量,释放内存 del locationDF fact_df.to_sql('Table2', schema='dbo', con=engine, if_exists='replace', method = 'multi', chunksize = 1000)
优化核心点:
- 读CSV时直接指定
usecols过滤不需要的列,内存占用直接减少70%以上 - 砍掉手动解析CSV的流程,直接用pandas内置的read_csv读取blob流,消除了四层中间数据副本
- 替换groupby阶段的自定义apply为内置聚合函数,避免额外的中间数据生成
- 及时删除不用的变量释放内存,适当调大to_sql的chunksize减少IO次数同时不会占用过多内存
- 修复原代码中
factdf.replace('', np.nan)未生效的bug(原代码未加inplace也未赋值)
Azure Function配置优化
- 如果你使用的是消费级计划,可将函数的内存配置从默认1.5GB升级到最高3GB
- 升级Python运行时版本到3.9及以上,新版本的内存管理效率更高
- 若仍有内存溢出问题,可切换到弹性Premium计划,选择EP2及以上的配置,获得更高的内存配额
内容的提问来源于stack exchange,提问作者Burján Balázs
相关产品推荐
相关产品推荐

