python脚本易被oom killer优先杀死,因其单进程内存占用高、oom_score值大;可通过调整oom_score_adj降分、分块读取数据、使用生成器、显式释放内存及配置swappiness和ulimit等综合防护。

为什么Python脚本总被OOM Killer第一个干掉?
因为OOM Killer默认按oom_score排序杀进程,而Python脚本(尤其用pandas、numpy或加载大模型时)往往单进程吃掉最多物理内存——它不是“最坏”的,但看起来“最肥”。日志里total-vm和anon-rss数值飙升、oom_score_adj:0就是典型信号。
调整oom_score_adj让Python进程“减刑”
这是最直接的防护动作,不改代码、不重启服务,只需给进程降分:
-
echo -500 > /proc/$(pgrep -f "python script.py")/oom_score_adj:立即保护指定脚本(注意权限,需root或同用户) - 如果用systemd管理,可在unit文件里加
OOMScoreAdjust=-500,避免每次启动重设 - 别设成-1000:这会让进程完全免疫OOM Killer,但若真占满内存,系统可能卡死而非优雅降级
- 子进程继承父进程的
oom_score_adj值,所以用subprocess.Popen启动的子任务也会受益
避免触发OOM的根本写法:别一次性 hold 所有数据
日志里看到Out of memory: Killed process ... (python),八成是代码在某处偷偷建了百万级列表或DataFrame。关键不是“有没有内存”,而是“要不要全放内存里”:
- 用
pandas.read_csv(..., chunksize=1000)代替pd.read_csv(),逐块处理 - 把
[x for x in huge_list]改成(x for x in huge_list),生成器不占堆内存 - 处理完一行数据后,显式
del掉中间变量,并调用gc.collect()(尤其在循环内) - 数据库查询别用
.all()或list(queryset),改用iterator()或游标分页
Linux系统层兜底:swappiness和ulimit别漏配
光靠代码和oom_score_adj不够,系统参数会放大或缓解风险:
-
sudo sysctl vm.swappiness=10:降低交换倾向,避免频繁swap拖慢并诱发OOM -
ulimit -v 4194304(单位KB):限制Python进程虚拟内存上限,提前报错MemoryError而非等OOM Killer动手 - 检查
/proc/meminfo里的MemAvailable,不是MemFree——后者忽略可回收缓存,容易误判 - swap分区存在但大小为0?那OOM Killer会更激进,建议至少配2GB swap用于紧急缓冲
真正麻烦的从来不是单点配置,而是oom_score_adj设了但代码还在疯狂append、swappiness调低了但ulimit没锁住——这些组合漏洞,才是半夜被“Killed”提醒叫醒的根源。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











