展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Python教程:用日志清洗脚本学会异常处理与生成器

Python教程:用日志清洗脚本学会异常处理与生成器

这篇 Python 教程通过一个真实可运行的日志清洗工具,讲解自定义异常、异常链、生成器、Counter、严格模式和退出状态。

本文目录

    刚开始写 Python 脚本时,最容易获得成就感的是“文件读出来了”。真正麻烦的部分往往出现在第三步:日志里混进一条坏数据,整个程序直接停了。

    全部忽略当然也能跑完,但你随后会遇到更难回答的问题:到底丢了多少行?为什么丢?自动化任务应该算成功还是失败?

    这篇 Python 教程不再重复变量和循环,而是完成一个可运行的日志清洗工具。输入一个 timestamp|level|message 格式的 UTF-8 日志文件,它会逐行校验数据、保留有效记录、统计日志级别,并把坏行原因放进 JSON 报告。脚本还提供严格模式,方便接进 CI 或定时任务。

    先把“正常”和“异常”写成规则

    我们先约定每行日志包含三个字段:

    2026-09-03T10:00:00|INFO|service started

    规则看起来很简单,但至少有四种输入不能悄悄放过:

    • 缺少分隔符,拆不出三个字段;
    • 时间不是 ISO 8601 格式;
    • 日志级别不在允许列表中;
    • 消息字段为空。

    这一步很重要。异常处理不是看到报错就套一层 try...except,而是先划清哪些问题可以恢复,哪些问题应该让程序停下来。

    当前工具把单条坏行视为“可恢复”:记录原因,继续处理后面的行。文件不存在、无权读取或者脚本自身出现未知错误,则不应该伪装成一次成功清洗。

    日志清洗脚本逐行读取并把有效记录和坏行原因分开的流程

    图:格式校验是分界点,有效记录继续参与汇总,坏行则保留具体原因。

    用自定义异常表达数据错误

    先实现一行日志的解析:

    from datetime import datetime
    
    
    VALID_LEVELS = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"}
    
    
    class LogFormatError(ValueError):
        """一行日志不符合 timestamp|level|message 约定。"""
    
    
    def parse_line(line: str, line_number: int) -> dict[str, str]:
        parts = line.rstrip("\n").split("|", 2)
        if len(parts) != 3:
            raise LogFormatError(f"第 {line_number} 行:字段数量不是 3")
    
        timestamp, level, message = (part.strip() for part in parts)
        try:
            datetime.fromisoformat(timestamp)
        except ValueError as exc:
            raise LogFormatError(
                f"第 {line_number} 行:时间不是 ISO 8601 格式"
            ) from exc
    
        level = level.upper()
        if level not in VALID_LEVELS:
            raise LogFormatError(f"第 {line_number} 行:未知级别 {level!r}")
        if not message:
            raise LogFormatError(f"第 {line_number} 行:消息为空")
    
        return {"timestamp": timestamp, "level": level, "message": message}

    这里有三个设计点。

    第一,split("|", 2) 最多拆两次。这样消息正文里即使包含 |,剩余内容仍会留在第三个字段中;直接使用不带次数限制的 split("|") 反而容易误伤正常消息。

    第二,输入中的 warning 会统一转换成 WARNING。这是可以恢复的格式差异,不需要把整行判坏。

    第三,时间解析产生的 ValueError 被转换成更贴合业务含义的 LogFormatError,同时通过 raise ... from exc 保留原异常链。Python 官方异常教程建议尽量捕获具体异常,让未预料的问题继续暴露,而不是用一个宽泛的 except Exception 把所有错误吞掉。

    为什么这里要用生成器

    解析一行之后,还要遍历整个文件。最直观的写法是先把所有结果放进列表,但我们其实只需要“取一条、处理一条”。生成器正适合表达这种过程:

    from pathlib import Path
    from typing import Iterator
    
    
    def iter_records(
        path: Path,
        errors: list[str],
    ) -> Iterator[dict[str, str]]:
        with path.open(encoding="utf-8") as log_file:
            for line_number, line in enumerate(log_file, start=1):
                if not line.strip():
                    continue
                try:
                    yield parse_line(line, line_number)
                except LogFormatError as exc:
                    errors.append(str(exc))

    函数中出现 yield 后,它返回的是生成器。调用方每请求下一条数据,函数才从上次暂停的位置继续执行。Python 官方教程把生成器描述为创建迭代器的一种紧凑方式,局部变量和执行位置会在两次取值之间保留下来。

    这意味着代码不需要先构造“全部有效记录”的列表。需要克制一点:这并不自动证明脚本在任何场景都更快,它只是改变了数据产生方式,减少了为有效记录额外保存完整列表的需要。实际性能仍取决于日志大小、磁盘和后续处理。

    errors 列表则是这版实现的现实取舍。它会保留所有错误文本,方便输出报告;如果坏行多到不可控,这个列表仍会占用内存。生产版本可以只保留前 N 条错误,再单独累计总数。

    Counter 把汇总逻辑压缩到一行

    有了有效记录流,就可以统计各级别出现次数:

    from collections import Counter
    
    
    def build_report(path: Path) -> dict[str, object]:
        errors: list[str] = []
        levels = Counter(
            record["level"]
            for record in iter_records(path, errors)
        )
        valid_lines = sum(levels.values())
    
        return {
            "file": str(path.resolve()),
            "valid_lines": valid_lines,
            "invalid_lines": len(errors),
            "levels": dict(sorted(levels.items())),
            "errors": errors,
        }

    Counter 是一个专门计数可哈希对象的字典子类。生成器每交出一条有效记录,Counter 就给对应的日志级别加一。最后再转回普通字典,让 JSON 输出更直观。

    为什么不把计数写进 parse_line()?因为解析函数应该只回答“这一行是否合法、解析结果是什么”。汇总是另一个层次的职责。两者拆开以后,后面改成按服务名或日期统计时,不必动底层格式校验。

    同一份报告,为什么需要两种退出策略

    交互运行脚本时,遇到几条坏行通常希望继续处理;接进数据流水线后,坏行又可能意味着上游格式已经变化,任务必须亮红灯。

    因此命令行增加一个 --strict 开关:

    import argparse
    import json
    
    
    def parse_args() -> argparse.Namespace:
        parser = argparse.ArgumentParser(
            description="清洗 timestamp|level|message 格式的 UTF-8 日志。"
        )
        parser.add_argument("log_file", type=Path, help="待处理日志文件")
        parser.add_argument(
            "--strict",
            action="store_true",
            help="发现坏行时返回非零状态",
        )
        return parser.parse_args()
    
    
    def main() -> int:
        args = parse_args()
        if not args.log_file.is_file():
            raise SystemExit(f"文件不存在:{args.log_file}")
    
        report = build_report(args.log_file)
        print(json.dumps(report, ensure_ascii=False, indent=2))
        return 2 if args.strict and report["invalid_lines"] else 0

    默认模式始终输出报告,发现坏行后继续处理,程序正常结束。严格模式也会输出相同报告,但只要存在坏行就返回退出码 2。Shell、CI 或定时任务可以据此判断这次清洗是否满足质量要求。

    日志清洗脚本发现坏行后在默认模式和严格模式之间的决策路径

    图:两种模式都保留报告,区别是严格模式会用非零退出状态通知自动化系统。

    运行真实样例,别只看代码猜结果

    把脚本保存为 log_cleaner.py,准备下面这份 sample-data/app.log:

    2026-09-03T10:00:00|INFO|service started
    2026-09-03T10:00:01|ERROR|database timeout
    this line is malformed
    2026-09-03T10:00:03|warning|queue depth high
    2026-09-03T10:00:04|TRACE|cache lookup
    2026-09-03T10:00:05|ERROR|retry exhausted

    在脚本所在目录执行:

    python3 log_cleaner.py sample-data/app.log

    本文示例在 Python 3.14.2 环境真实运行,关键输出如下:

    {
      "valid_lines": 4,
      "invalid_lines": 2,
      "levels": {
        "ERROR": 2,
        "INFO": 1,
        "WARNING": 1
      },
      "errors": [
        "第 3 行:字段数量不是 3",
        "第 5 行:未知级别 'TRACE'"
      ]
    }

    绝对文件路径在上面的节选中省略,完整输出会保留 file 字段。

    再运行严格模式:

    python3 log_cleaner.py sample-data/app.log --strict
    echo $?

    实测退出码是 2。这不是异常崩溃,而是脚本按约定主动给调用方的质量信号。

    测试要覆盖坏数据,而不只是正常路径

    这类工具最值得测的恰恰是异常输入:

    def test_report_separates_valid_and_invalid_lines(self) -> None:
        source.write_text(
            "2026-09-03T10:00:00|INFO|started\n"
            "bad line\n"
            "2026-09-03T10:00:01|error|timeout\n"
            "2026-09-03T10:00:02|TRACE|unknown level\n",
            encoding="utf-8",
        )
    
        report = build_report(source)
    
        self.assertEqual(report["valid_lines"], 2)
        self.assertEqual(report["invalid_lines"], 2)
        self.assertEqual(report["levels"], {"ERROR": 1, "INFO": 1})

    完整示例还测试了严格模式的退出码。实际执行:

    python3 -m unittest -v test_log_cleaner.py

    结果为 2 tests OK,脚本和测试文件也通过了 py_compile 语法检查。

    这份脚本的边界在哪里

    它适合学习和处理格式明确的小型文本日志,但还不是通用日志平台:

    1. 分隔格式是自定义约定,不支持多行消息;
    2. 只处理 UTF-8,其他编码会在文件读取阶段失败;
    3. ISO 时间只校验格式,没有统一时区;
    4. 所有坏行原因都会留在内存中;
    5. 统计结果只按日志级别聚合,没有时间窗口和服务维度。

    下一步可以增加 --max-errors 限制错误样本数量,要求时间必须带时区,并把有效记录写成 JSON Lines。日志量继续增大后,再考虑批量落盘、压缩输入和并行处理;在没有测量数据前,不要先承诺性能提升。

    这次真正要带走的不是某个固定日志格式,而是一条可复用的 Python 编程路径:把输入规则写清楚,用具体异常表达可预期错误,用生成器逐条交付数据,再通过退出状态把结果告诉外部系统。遇到下一个文件处理任务时,这套拆法仍然成立。

    参考资料

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 python教程
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    Beamer 4 macOS版
    Beamer 4 macOS版

    Beamer 4是面向macOS的本地视频投屏工具,可将Mac中的影片投放到Apple TV、Chromecast及兼容设备,支持常见格式、多类字幕、环绕声、播放列表和电视遥控操作。

    WINDOWS 更多
    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

    AlwaysUp Windows版
    AlwaysUp Windows版

    AlwaysUp是一款面向Windows的系统服务注册与程序托管工具,可让普通应用、脚本及批处理在无人登录时随系统启动,并通过状态检测、异常重启、资源监控和邮件通知保障关键任务持续运行。

    AnyDesk Windows版
    AnyDesk Windows版

    AnyDesk Windows版是一款轻量化远程桌面与技术支持工具,可用于控制异地电脑、传输文件、远程打印及无人值守访问。它兼顾连接响应、安全权限和部署灵活性,适合个人远程办公、企业设备维护与客服支持。