Python 日志分析实战:用 Counter 三行代码统计高频错误

举报
yd_70403235 发表于 2026/11/02 09:09:22 2026/11/02
【摘要】 线上服务跑久了,日志文件里最常被问到的问题只有一个:到底是哪些错误出现得最频繁?直接打开几百兆的日志文件肉眼翻,既慢又容易漏。本文用 Python 标准库里的 collections.Counter,配合一行正则,把“统计高频错误”做成一个可以反复用的小脚本。文中的两段核心代码已经在华为云 AI DevSpace(Python 3.11.16)里实际运行验证过。 一、先看“笨办法”:手写字典...

线上服务跑久了,日志文件里最常被问到的问题只有一个:到底是哪些错误出现得最频繁?

直接打开几百兆的日志文件肉眼翻,既慢又容易漏。本文用 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;
  • 处理真实日志文件时坚持逐行读取,内存占用只与单行长度有关。

下次再遇到“先看看哪类错误最多”的需求,这个十几行的小脚本可以直接拿去用。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。