Python 日志分析实战:用 Counter 三行代码统计高频错误
线上服务跑久了,日志文件里最常被问到的问题只有一个:到底是哪些错误出现得最频繁?
直接打开几百兆的日志文件肉眼翻,既慢又容易漏。本文用 Python 标准库里的 collections.Counter,配合一行正则,把“统计高频错误”做成一个可以反复用的小脚本。文中的两段核心代码已经在华为云 AI DevSpace(Python 3.11.16)里实际运行验证过。
一、先看“笨办法”:手写字典统计
很多初学者会这样写:
stats = {}
for line in logs:
if line.startswith("ERROR"):
code = line.split()[1]
if code in stats:
stats[code] += 1
else:
stats[code] = 1
能跑,但有两个问题:一是 if/else 样板代码多,二是 split()[1] 依赖日志格式固定不变,一旦多了一个字段就取错位置。
二、核心写法:Counter + 正则
from collections import Counter
import re
logs = [
"ERROR 500 Internal Server Error",
"ERROR 404 Not Found",
"ERROR 500 Internal Server Error",
"INFO 200 OK",
"ERROR 500 Internal Server Error",
]
codes = [re.search(r"ERROR (\d+)", line).group(1)
for line in logs if line.startswith("ERROR")]
print(Counter(codes).most_common(2))
运行输出:
[('500', 3), ('404', 1)]
核心逻辑只有三行:先用 startswith("ERROR") 过滤出错误行,再用正则 ERROR (\d+) 稳稳地取出状态码,最后交给 Counter.most_common(2) 直接排出前两名。Counter 本身就是 dict 的子类,计数、排序一步到位,不用自己维护 if/else。
三、再进一步:顺手算出占比
只知道次数还不够,排障时更关心“500 错误占了几成”:
from collections import Counter
counter = Counter({"500": 3, "404": 1})
total = sum(counter.values())
print([(code, num, str(round(num / total * 100)) + "%")
for code, num in counter.most_common()])
运行输出:
[('500', 3, '75%'), ('404', 1, '25%')]
500 错误占了四分之三,结论一目了然:先修 500,再看 404。
四、用到真实日志文件上
真实场景的日志在文件里,不在列表里。把上面思路换成逐行读取,就能直接处理大文件:
from collections import Counter
import re
pattern = re.compile(r"ERROR (\d+)")
counter = Counter()
with open("app.log", encoding="utf-8") as f:
for line in f:
match = pattern.search(line)
if match:
counter[match.group(1)] += 1
print(counter.most_common(5))
注意两点:一是 re.compile 把正则预编译好,避免每行重复编译;二是 for line in f 逐行读文件,哪怕日志有几个 GB,也不会一次吃掉全部内存。
五、小结
- 统计频次优先用
Counter,不要手写if/else计数; - 取结构化字段用正则,比固定下标
split()[1]更稳; most_common(n)一步给出 Top N;- 处理真实日志文件时坚持逐行读取,内存占用只与单行长度有关。
下次再遇到“先看看哪类错误最多”的需求,这个十几行的小脚本可以直接拿去用。
- 点赞
- 收藏
- 关注作者
评论(0)