欢迎光临
我们一直在努力

Python 文件读写、JSON 与异常处理,让程序从课堂练习变成可用工具

前面几篇文章里的程序,大多有一个共同问题。

数据只存在内存里。

程序一关,用户输入过什么,计算出什么结果,全都没了。

真实工具不可能这样。它需要读取文件、保存数据、处理错误,遇到问题时给出明确提示,而不是直接崩溃。

这篇文章讲三个很实用的能力:

  • 文件读写。
  • JSON 数据保存。
  • 异常处理。
  • 学完之后,你就能写一个能保存数据的小工具。

    文件路径先讲清楚

    文件读写最容易出问题的不是语法,而是路径。

    看这行:

    with open("note.txt", "r", encoding="utf-8") as file:
    content = file.read()

    note.txt 是相对路径。

    它不是永远相对于代码文件所在目录,而是相对于程序运行时的当前工作目录。

    这就是为什么有时候你明明把文件放在旁边,程序却说找不到。

    更稳的方式是用 pathlib:

    from pathlib import Path

    BASE_DIR = Path(__file__).resolve().parent
    note_path = BASE_DIR / "note.txt"

    with note_path.open("r", encoding="utf-8") as file:
    content = file.read()

    print(content)

    Path(__file__).resolve().parent 表示当前 Python 文件所在目录。

    这样不管你从哪里运行程序,读取的都是代码文件旁边的 note.txt。

    文件路径关系可以画成这样:

    #mermaid-svg-AcrDdo6lPxMr0gU6{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-AcrDdo6lPxMr0gU6 .error-icon{fill:#552222;}#mermaid-svg-AcrDdo6lPxMr0gU6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AcrDdo6lPxMr0gU6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .marker.cross{stroke:#333333;}#mermaid-svg-AcrDdo6lPxMr0gU6 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AcrDdo6lPxMr0gU6 p{margin:0;}#mermaid-svg-AcrDdo6lPxMr0gU6 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster-label text{fill:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster-label span{color:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster-label span p{background-color:transparent;}#mermaid-svg-AcrDdo6lPxMr0gU6 .label text,#mermaid-svg-AcrDdo6lPxMr0gU6 span{fill:#333;color:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .node rect,#mermaid-svg-AcrDdo6lPxMr0gU6 .node circle,#mermaid-svg-AcrDdo6lPxMr0gU6 .node ellipse,#mermaid-svg-AcrDdo6lPxMr0gU6 .node polygon,#mermaid-svg-AcrDdo6lPxMr0gU6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .rough-node .label text,#mermaid-svg-AcrDdo6lPxMr0gU6 .node .label text,#mermaid-svg-AcrDdo6lPxMr0gU6 .image-shape .label,#mermaid-svg-AcrDdo6lPxMr0gU6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-AcrDdo6lPxMr0gU6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .rough-node .label,#mermaid-svg-AcrDdo6lPxMr0gU6 .node .label,#mermaid-svg-AcrDdo6lPxMr0gU6 .image-shape .label,#mermaid-svg-AcrDdo6lPxMr0gU6 .icon-shape .label{text-align:center;}#mermaid-svg-AcrDdo6lPxMr0gU6 .node.clickable{cursor:pointer;}#mermaid-svg-AcrDdo6lPxMr0gU6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .arrowheadPath{fill:#333333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AcrDdo6lPxMr0gU6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-AcrDdo6lPxMr0gU6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AcrDdo6lPxMr0gU6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster text{fill:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 .cluster span{color:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AcrDdo6lPxMr0gU6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-AcrDdo6lPxMr0gU6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-AcrDdo6lPxMr0gU6 .icon-shape,#mermaid-svg-AcrDdo6lPxMr0gU6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-AcrDdo6lPxMr0gU6 .icon-shape p,#mermaid-svg-AcrDdo6lPxMr0gU6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-AcrDdo6lPxMr0gU6 .icon-shape .label rect,#mermaid-svg-AcrDdo6lPxMr0gU6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-AcrDdo6lPxMr0gU6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-AcrDdo6lPxMr0gU6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-AcrDdo6lPxMr0gU6 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    运行命令所在目录

    相对路径查找位置

    代码文件所在目录

    Path(__file__).parent

    可能和代码目录不同

    更适合定位项目内文件

    文本文件怎么写

    写入文件:

    from pathlib import Path

    note_path = Path("note.txt")

    with note_path.open("w", encoding="utf-8") as file:
    file.write("今天学习 Python 文件读写")

    w 表示写入。文件不存在会创建,文件存在会覆盖。

    追加内容:

    from pathlib import Path

    note_path = Path("note.txt")

    with note_path.open("a", encoding="utf-8") as file:
    file.write("\\n继续学习 JSON 和异常处理")

    a 表示追加,不会覆盖原内容。

    读取文件:

    from pathlib import Path

    note_path = Path("note.txt")

    with note_path.open("r", encoding="utf-8") as file:
    content = file.read()

    print(content)

    这里建议始终使用 with。

    原因是 with 代码块结束后,文件会自动关闭。你不用手动写 close(),也不容易忘。

    read、readline、readlines 怎么选

    一次性读取全部内容:

    with open("note.txt", "r", encoding="utf-8") as file:
    content = file.read()

    逐行读取:

    with open("note.txt", "r", encoding="utf-8") as file:
    for line in file:
    print(line.strip())

    读取成列表:

    with open("note.txt", "r", encoding="utf-8") as file:
    lines = file.readlines()

    print(lines)

    选择标准:

    小文件可以 read()。

    大文件更适合逐行读取,避免一次性占用太多内存。

    如果后续确实要按行组成列表,再用 readlines()。

    为什么总要写 encoding="utf-8"

    如果文件里有中文,编码必须认真对待。

    with open("note.txt", "w", encoding="utf-8") as file:
    file.write("你好,Python")

    不同系统默认编码可能不同。

    你不写 encoding,在自己电脑上可能没事,换一台电脑就乱码。

    所以中文文件统一写 encoding="utf-8",这是一个好习惯。

    如果 CSV 要给 Excel 打开,有时可以用 utf-8-sig,但普通文本和 JSON 用 utf-8 就很好。

    JSON 是什么

    JSON 是一种保存结构化数据的文本格式。

    它长得像 Python 字典,但不是 Python 字典。

    JSON 文本:

    {
    "name": "小明",
    "age": 18,
    "skills": ["Python", "AI"]
    }

    Python 数据:

    user = {
    "name": "小明",
    "age": 18,
    "skills": ["Python", "AI"]
    }

    二者可以互相转换:

    #mermaid-svg-Smim3JO97gXG1SPH{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Smim3JO97gXG1SPH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Smim3JO97gXG1SPH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Smim3JO97gXG1SPH .error-icon{fill:#552222;}#mermaid-svg-Smim3JO97gXG1SPH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Smim3JO97gXG1SPH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Smim3JO97gXG1SPH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Smim3JO97gXG1SPH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Smim3JO97gXG1SPH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Smim3JO97gXG1SPH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Smim3JO97gXG1SPH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Smim3JO97gXG1SPH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Smim3JO97gXG1SPH .marker.cross{stroke:#333333;}#mermaid-svg-Smim3JO97gXG1SPH svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Smim3JO97gXG1SPH p{margin:0;}#mermaid-svg-Smim3JO97gXG1SPH .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Smim3JO97gXG1SPH .cluster-label text{fill:#333;}#mermaid-svg-Smim3JO97gXG1SPH .cluster-label span{color:#333;}#mermaid-svg-Smim3JO97gXG1SPH .cluster-label span p{background-color:transparent;}#mermaid-svg-Smim3JO97gXG1SPH .label text,#mermaid-svg-Smim3JO97gXG1SPH span{fill:#333;color:#333;}#mermaid-svg-Smim3JO97gXG1SPH .node rect,#mermaid-svg-Smim3JO97gXG1SPH .node circle,#mermaid-svg-Smim3JO97gXG1SPH .node ellipse,#mermaid-svg-Smim3JO97gXG1SPH .node polygon,#mermaid-svg-Smim3JO97gXG1SPH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Smim3JO97gXG1SPH .rough-node .label text,#mermaid-svg-Smim3JO97gXG1SPH .node .label text,#mermaid-svg-Smim3JO97gXG1SPH .image-shape .label,#mermaid-svg-Smim3JO97gXG1SPH .icon-shape .label{text-anchor:middle;}#mermaid-svg-Smim3JO97gXG1SPH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Smim3JO97gXG1SPH .rough-node .label,#mermaid-svg-Smim3JO97gXG1SPH .node .label,#mermaid-svg-Smim3JO97gXG1SPH .image-shape .label,#mermaid-svg-Smim3JO97gXG1SPH .icon-shape .label{text-align:center;}#mermaid-svg-Smim3JO97gXG1SPH .node.clickable{cursor:pointer;}#mermaid-svg-Smim3JO97gXG1SPH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Smim3JO97gXG1SPH .arrowheadPath{fill:#333333;}#mermaid-svg-Smim3JO97gXG1SPH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Smim3JO97gXG1SPH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Smim3JO97gXG1SPH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Smim3JO97gXG1SPH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Smim3JO97gXG1SPH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Smim3JO97gXG1SPH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Smim3JO97gXG1SPH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Smim3JO97gXG1SPH .cluster text{fill:#333;}#mermaid-svg-Smim3JO97gXG1SPH .cluster span{color:#333;}#mermaid-svg-Smim3JO97gXG1SPH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Smim3JO97gXG1SPH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Smim3JO97gXG1SPH rect.text{fill:none;stroke-width:0;}#mermaid-svg-Smim3JO97gXG1SPH .icon-shape,#mermaid-svg-Smim3JO97gXG1SPH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Smim3JO97gXG1SPH .icon-shape p,#mermaid-svg-Smim3JO97gXG1SPH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Smim3JO97gXG1SPH .icon-shape .label rect,#mermaid-svg-Smim3JO97gXG1SPH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Smim3JO97gXG1SPH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Smim3JO97gXG1SPH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Smim3JO97gXG1SPH :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    json.dump / json.dumps

    json.load / json.loads

    Python dict / list

    JSON 文本

    dump、dumps、load、loads

    这四个函数名字很像,但规则很简单。

    带 s 的处理字符串。

    不带 s 的处理文件。

    写入 JSON 文件:

    import json

    user = {
    "name": "小明",
    "age": 18,
    "skills": ["Python", "AI"]
    }

    with open("user.json", "w", encoding="utf-8") as file:
    json.dump(user, file, ensure_ascii=False, indent=2)

    ensure_ascii=False 可以让中文正常保存。

    indent=2 让文件更容易阅读。

    读取 JSON 文件:

    import json

    with open("user.json", "r", encoding="utf-8") as file:
    user = json.load(file)

    print(user["name"])

    转成 JSON 字符串:

    import json

    user = {"name": "小明", "age": 18}
    text = json.dumps(user, ensure_ascii=False)

    print(text)

    从 JSON 字符串解析:

    import json

    text = '{"name": "小明", "age": 18}'
    user = json.loads(text)

    print(user["age"])

    JSON 类型映射

    PythonJSON
    dict object
    list / tuple array
    str string
    int / float number
    True true
    False false
    None null

    注意,JSON 里没有元组,Python 元组保存成 JSON 后会变成数组,读回来通常是列表。

    异常是什么

    异常就是程序运行过程中遇到的问题。

    比如:

    age = int(input("请输入年龄:"))
    print(age + 1)

    如果用户输入 十八,就会抛出 ValueError。

    如果读取不存在的文件:

    with open("missing.txt", "r", encoding="utf-8") as file:
    print(file.read())

    会抛出 FileNotFoundError。

    异常处理的目标不是掩盖错误,而是让可预期的错误有清楚反馈。

    try…except

    try:
    age = int(input("请输入年龄:"))
    print(age + 1)
    except ValueError:
    print("年龄必须输入数字")

    如果 try 里的代码出错,并且错误类型是 ValueError,就执行 except。

    捕获文件不存在:

    try:
    with open("note.txt", "r", encoding="utf-8") as file:
    content = file.read()
    print(content)
    except FileNotFoundError:
    print("文件不存在,请先创建 note.txt")

    else 和 finally

    else 表示没有异常时执行。

    finally 表示不管有没有异常都会执行。

    try:
    number = int(input("请输入数字:"))
    except ValueError:
    print("输入不是数字")
    else:
    print(f"你输入的是 {number}")
    finally:
    print("程序结束")

    常见流程:

    #mermaid-svg-fYAyaYcioFYwGazB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fYAyaYcioFYwGazB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fYAyaYcioFYwGazB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fYAyaYcioFYwGazB .error-icon{fill:#552222;}#mermaid-svg-fYAyaYcioFYwGazB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fYAyaYcioFYwGazB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fYAyaYcioFYwGazB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fYAyaYcioFYwGazB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fYAyaYcioFYwGazB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fYAyaYcioFYwGazB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fYAyaYcioFYwGazB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fYAyaYcioFYwGazB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fYAyaYcioFYwGazB .marker.cross{stroke:#333333;}#mermaid-svg-fYAyaYcioFYwGazB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fYAyaYcioFYwGazB p{margin:0;}#mermaid-svg-fYAyaYcioFYwGazB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fYAyaYcioFYwGazB .cluster-label text{fill:#333;}#mermaid-svg-fYAyaYcioFYwGazB .cluster-label span{color:#333;}#mermaid-svg-fYAyaYcioFYwGazB .cluster-label span p{background-color:transparent;}#mermaid-svg-fYAyaYcioFYwGazB .label text,#mermaid-svg-fYAyaYcioFYwGazB span{fill:#333;color:#333;}#mermaid-svg-fYAyaYcioFYwGazB .node rect,#mermaid-svg-fYAyaYcioFYwGazB .node circle,#mermaid-svg-fYAyaYcioFYwGazB .node ellipse,#mermaid-svg-fYAyaYcioFYwGazB .node polygon,#mermaid-svg-fYAyaYcioFYwGazB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fYAyaYcioFYwGazB .rough-node .label text,#mermaid-svg-fYAyaYcioFYwGazB .node .label text,#mermaid-svg-fYAyaYcioFYwGazB .image-shape .label,#mermaid-svg-fYAyaYcioFYwGazB .icon-shape .label{text-anchor:middle;}#mermaid-svg-fYAyaYcioFYwGazB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fYAyaYcioFYwGazB .rough-node .label,#mermaid-svg-fYAyaYcioFYwGazB .node .label,#mermaid-svg-fYAyaYcioFYwGazB .image-shape .label,#mermaid-svg-fYAyaYcioFYwGazB .icon-shape .label{text-align:center;}#mermaid-svg-fYAyaYcioFYwGazB .node.clickable{cursor:pointer;}#mermaid-svg-fYAyaYcioFYwGazB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fYAyaYcioFYwGazB .arrowheadPath{fill:#333333;}#mermaid-svg-fYAyaYcioFYwGazB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fYAyaYcioFYwGazB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fYAyaYcioFYwGazB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fYAyaYcioFYwGazB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fYAyaYcioFYwGazB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fYAyaYcioFYwGazB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fYAyaYcioFYwGazB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fYAyaYcioFYwGazB .cluster text{fill:#333;}#mermaid-svg-fYAyaYcioFYwGazB .cluster span{color:#333;}#mermaid-svg-fYAyaYcioFYwGazB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fYAyaYcioFYwGazB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fYAyaYcioFYwGazB rect.text{fill:none;stroke-width:0;}#mermaid-svg-fYAyaYcioFYwGazB .icon-shape,#mermaid-svg-fYAyaYcioFYwGazB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fYAyaYcioFYwGazB .icon-shape p,#mermaid-svg-fYAyaYcioFYwGazB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fYAyaYcioFYwGazB .icon-shape .label rect,#mermaid-svg-fYAyaYcioFYwGazB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fYAyaYcioFYwGazB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fYAyaYcioFYwGazB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fYAyaYcioFYwGazB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    进入 try

    是否发生异常?

    执行 except

    执行 else

    执行 finally

    不要乱用 except Exception

    下面写法能抓很多错误:

    try:
    number = int(input("请输入数字:"))
    except Exception:
    print("出错了")

    但它的问题是太宽。

    你不知道到底出了什么错,也可能把真正应该修复的 bug 藏起来。

    更好的方式是捕获具体异常:

    try:
    number = int(input("请输入数字:"))
    except ValueError:
    print("请输入合法数字")

    只有当你确实需要兜底处理,并且会记录错误信息时,才考虑捕获更宽的异常。

    完整案例,学习记录工具

    这个工具会:

  • 读取已有学习记录。
  • 追加一条新记录。
  • 保存回 JSON 文件。
  • 文件不存在时自动创建。
  • import json
    from pathlib import Path

    BASE_DIR = Path(__file__).resolve().parent
    RECORD_FILE = BASE_DIR / "study_records.json"

    def load_records() > list[dict]:
    """读取学习记录,文件不存在时返回空列表。"""
    if not RECORD_FILE.exists():
    return []

    with RECORD_FILE.open("r", encoding="utf-8") as file:
    return json.load(file)

    def save_records(records: list[dict]) > None:
    """保存学习记录到 JSON 文件。"""
    with RECORD_FILE.open("w", encoding="utf-8") as file:
    json.dump(records, file, ensure_ascii=False, indent=2)

    name = input("请输入姓名:")
    course = input("请输入课程名:")
    days = int(input("请输入学习天数:"))

    records = load_records()
    records.append({
    "name": name,
    "course": course,
    "days": days
    })

    save_records(records)

    print("学习记录已保存")

    这个例子已经是一个小工具了。

    它不只是打印结果,还能把数据保存下来。

    常见错误和修复

    FileNotFoundError

    原因:文件路径不存在。

    修复:

  • 检查当前工作目录。
  • 使用 Path(__file__).parent 定位代码所在目录。
  • 读取前判断 path.exists()。
  • JSONDecodeError

    原因:JSON 文件内容格式不合法。

    比如少了一个逗号,或者文件是空的。

    处理方式:

    import json

    try:
    with open("user.json", "r", encoding="utf-8") as file:
    user = json.load(file)
    except json.JSONDecodeError:
    print("JSON 文件格式不正确")

    中文乱码

    原因:写入和读取编码不一致。

    修复:

    写入和读取都统一:

    encoding="utf-8"

    数字输入错误

    原因:用户输入的不是合法数字。

    修复:

    try:
    days = int(input("请输入学习天数:"))
    except ValueError:
    print("学习天数必须是整数")

    练习,做一个通讯录

    要求:

  • 用户输入姓名和手机号。
  • 保存到 contacts.json。
  • 支持多次追加联系人。
  • 文件不存在时自动创建。
  • 参考代码可以沿用上面的学习记录工具,把字段改成 name 和 phone。

    参考资料

    • Python 输入输出教程:https://docs.python.org/3/tutorial/inputoutput.html
    • Python 异常教程:https://docs.python.org/3/tutorial/errors.html
    • Python JSON 文档:https://docs.python.org/3/library/json.html
    赞(0)
    未经允许不得转载:171主机测评 » Python 文件读写、JSON 与异常处理,让程序从课堂练习变成可用工具
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址