查看全课大纲(第 45 / 51 节)
  1. 1.为什么人人都该学点编程?
  2. 2.计算机与程序设计:你的电脑到底在“想”什么?
  3. 3.Python 这门语言,到底有什么魔力?
  4. 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
  5. 5.如何安装一个更强大的代码编辑器?
  6. 6.汇率兑换1.0:你的第一个“钱生钱”小程序
  7. 7.你的第一行代码,藏着哪些秘密?
  8. 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
  9. 9.汇率兑换程序,如何让它“聪明”地判断币种?
  10. 10.汇率兑换程序能一直运行,直到我喊停吗?
  11. 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
  12. 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
  13. 13.怎么用 Python 画一个会动的五角星?
  14. 14.如何让程序自动画出不同大小的五角星?
  15. 15.函数自己调用自己,会发生什么?
  16. 16.用递归画出神奇的分形树
  17. 17.Python 怎么计算你一天躺着不动能消耗多少热量?
  18. 18.如何让程序“活”起来,持续为你服务?
  19. 19.如何让 BMR 计算器更“聪明”?
  20. 20.当程序遇到“不按套路出牌”的用户怎么办?
  21. 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
  22. 22.如何用列表记录每一周的存款?
  23. 23.如何让程序自己数数?—— 用 for 循环解放你的双手
  24. 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
  25. 25.52周存钱挑战:怎么根据日期自动查存款?
  26. 26.Python 怎么判断一年中的第几天?
  27. 27.列表 vs 元组:哪个更适合存储月份天数?
  28. 28.用集合给月份分个队,换个思路算天数
  29. 29.把月份和天数“锁”在一起:用字典给数据配个对
  30. 30.Python 怎么判断密码强弱?
  31. 31.Python 怎么给密码设置“防沉迷”系统?
  32. 32.Python 怎么把密码保存到文件里?
  33. 33.Python 怎么读取文件里的密码?
  34. 34.Python 怎么把密码检查工具“打包”起来?
  35. 35.Python 怎么把文件操作也“打包”起来?
  36. 36.计算机怎么“扔骰子”?——用Python模拟随机事件
  37. 37.如何用 Python 模拟掷两个骰子?
  38. 38.怎么用 Python 把骰子轨迹画出来?
  39. 39.骰子点数分布长啥样?用直方图一眼看穿!
  40. 40.用科学计算库让骰子程序“起飞”
  41. 41.空气质量指数怎么算?手把手教你写一个AQI计算器
  42. 42.空气质量指数计算:从零开始,让程序看懂空气
  43. 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
  44. 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
  45. 45.Python 怎么让程序自己判断文件类型?
  46. 46.如何让程序自己上网查空气质量?
  47. 47.用美味的汤来解析网页:Beautiful Soup 入门
  48. 48.如何让爬虫自动抓取全国所有城市的空气质量?
  49. 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
  50. 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
  51. 51.空气质量数据怎么“洗”干净,还能画成图?

Python 怎么让程序自己判断文件类型?

约 11 分钟

小象实战讲义 · Python 入门:8 个小项目边玩边学

你好呀!欢迎来到空气质量指数计算项目的第 4 步。在前两节里,我们学会了用 Python 读取 JSON 和 CSV 这两种格式的数据文件。现在,我们来玩点更酷的:写一个“聪明”的程序,让它自己判断你给的文件是 JSON 还是 CSV,然后自动用正确的方法打开它!

想象一下,你有一个文件夹,里面既有 .json 文件,也有 .csv 文件。你不想每次打开前都手动判断,而是希望程序能自动帮你搞定。这就是我们这节课要实现的“文件格式自动识别器”。

💡 核心导读

本节我们将一起完成:

  • 认识一位新朋友:os 模块,它能帮我们轻松获取文件的扩展名(比如 .json 或 .csv)。
  • 学会一个更优雅的文件操作方式:with 语句,从此再也不用担心忘记关闭文件了!
  • 整合之前的知识,用 if...elif...else 判断文件类型,并调用对应的处理函数。
  • 本节新增了什么? 我们只新增了 os.path.splitext() 这个函数来提取文件扩展名,并用 with 语句优化了文件操作。其他都是老朋友啦!

1. 回顾与目标:让程序“聪明”起来

在前两节,我们分别写了处理 JSON 文件的程序和处理 CSV 文件的程序。但它们是分开的。如果我想处理一个文件,还得先看看它是什么格式,再决定运行哪个程序,这太不“智能”了。

我们这节课的目标,就是写一个统一的入口程序。你只需要告诉它文件名,它就能自己判断格式,并调用正确的处理逻辑。

案例描述:编写一个程序,根据用户输入的文件路径,自动判断该文件是 JSON 格式还是 CSV 格式,并分别进行读取和内容展示。

2. 新技能:用 os 模块获取文件信息

怎么判断一个文件是 .json 还是 .csv 呢?最直接的办法就是看文件名最后那几个字符(也就是扩展名)。Python 的 os 模块里有一个超好用的工具 os.path.splitext(),专门干这个。

os 模块是 Python 和操作系统打交道的“瑞士军刀”,可以干很多事,比如创建文件夹、删除文件、检查路径等等。我们今天只请它帮一个小忙。

# 让我们先感受一下 os.path.splitext() 的魔力
import os

# 假设我们有一个文件路径
file_path = "上海空气质量.json"

# 使用 splitext 分割
filename, file_ext = os.path.splitext(file_path)

print(f"文件名部分是:{filename}")
print(f"扩展名部分是:{file_ext}")
文件名部分是:上海空气质量
扩展名部分是:.json

看!它把文件名和扩展名干净利落地分开了,而且扩展名是带点(.) 的。这样我们判断起来就非常方便了。

3. 再学一招:更安全的文件操作 with

还记得我们操作文件的“三步曲”吗?打开 → 操作 → 关闭。有时候一忙起来,很容易忘记最后那步 close(),这可能会导致资源没被释放。

Python 提供了一个更优雅、更安全的写法:with 语句。它的好处是,无论文件操作是否成功,是否发生错误,它都会在代码块结束后自动帮你关闭文件。再也不用担心忘记关文件啦!

我们来对比一下新旧写法:

import os

# 本节需要 example.txt(课程 resources 附件提供);为便于单独运行,先用示例数据建一份
with open('example.txt', 'w', encoding='utf-8') as f:   # 示例数据:每次运行都重建,保证输出一致
    f.write("拼接后的完整路径是:data\\\\test.csv\n多层目录拼接:project\\\\data\\\\2023\\\\result.json")
# 旧写法:需要手动关闭
f = open('example.txt', 'r')
content = f.read()
print(content)
f.close()  # 容易忘记!

# 新写法(推荐!):使用 with 语句
with open('example.txt', 'r') as f:
    content = f.read()
    print(content)
# 出了 with 这个代码块,文件会自动关闭,不需要写 f.close()
拼接后的完整路径是:data\\test.csv
多层目录拼接:project\\data\\2023\\result.json
拼接后的完整路径是:data\\test.csv
多层目录拼接:project\\data\\2023\\result.json

是不是简洁又安心?我们这节课就会用这个新写法来重写文件处理部分。

4. 动手实现:文件格式自动判断程序

好了,新工具都准备好了,让我们把它们组装起来,写出我们的 v4.0 程序。

核心思路:

  1. 获取用户输入的文件名。
  2. 用 os.path.splitext() 提取扩展名。
  3. 判断扩展名:
    • 如果是 .json,就调用处理 JSON 的函数。
    • 如果是 .csv,就调用处理 CSV 的函数。
    • 如果都不是,就提示用户格式不支持。
  4. 在处理函数中,使用 with 语句安全地读取文件。

下面是完整的程序,我们把 JSON 和 CSV 的处理逻辑分别封装成了函数。

"""
    作者:小象教研组
    功能:AQI计算 - 自动判断文件格式 (v4.0)
    版本:4.0
"""
import json
import csv
import os
# 本节需要 上海空气质量.json(课程 resources 附件提供);为便于单独运行,先用示例数据建一份
with open('上海空气质量.json', 'w', encoding='utf-8') as f:   # 示例数据:每次运行都重建,保证输出一致
    f.write('[{"aqi": "51", "area": "北京"}, {"aqi": "102", "area": "顺义"}]')

def process_json_file(filepath):
    """
        处理json文件:读取并打印内容
    """
    # 使用 with 语句,安全又省心
    with open(filepath, mode='r', encoding='utf-8') as f:
        # json.load() 可以直接从文件对象读取数据
        city_list = json.load(f)
    print("=== JSON 文件内容 ===")
    print(city_list)

def process_csv_file(filepath):
    """
        处理csv文件:读取并打印每一行
    """
    # 注意:csv读取时指定 newline='' 可以避免空行问题
    with open(filepath, mode='r', encoding='utf-8', newline='') as f:
        reader = csv.reader(f)
        print("=== CSV 文件内容(每行是一个列表)===")
        for row in reader:
            # row 是一个列表,我们用逗号把它连接成一个字符串打印
            print(', '.join(row))

def main():
    """
        主函数:判断文件格式并分发处理
    """
    # 原程序这里用 input(),为了你能直接运行,我们先给一个固定值
    # 你可以改成 '上海空气质量.json' 或 '上海空气质量.csv' 试试
    filepath = '上海空气质量.json'

    # 使用 os.path.splitext 获取扩展名
    filename, file_ext = os.path.splitext(filepath)
    print(f"正在检查文件:{filepath}")
    print(f"检测到扩展名:{file_ext}")

    # 根据扩展名决定如何处理
    if file_ext == '.json':
        print("识别为 JSON 文件,开始处理...")
        process_json_file(filepath)
    elif file_ext == '.csv':
        print("识别为 CSV 文件,开始处理...")
        process_csv_file(filepath)
    else:
        print(f'抱歉,不支持 {file_ext} 格式的文件!')

# 启动程序
main()
正在检查文件:上海空气质量.json
检测到扩展名:.json
识别为 JSON 文件,开始处理...
=== JSON 文件内容 ===
[{'aqi': '51', 'area': '北京'}, {'aqi': '102', 'area': '顺义'}]

代码说明:

  • process_json_file 和 process_csv_file 函数封装了各自格式的处理细节,主程序 main() 变得非常清晰。
  • 在 process_csv_file 中,我们用了 ', '.join(row)。join() 是字符串的方法,它能把一个列表里的所有元素,用指定的字符串(这里是 ', ')连接起来,变成一个新的字符串。这样打印出来更美观。
  • 主逻辑就是一个清晰的 if-elif-else 判断,根据 file_ext 的值来“派活”。

运行一下看看: 你需要准备两个小文件来测试。我们这里用内联数据模拟一下文件内容,实际练习时你可以用课程提供的真实数据文件。

# 模拟测试:我们先在代码里创建两个临时文件内容来演示
import json
import csv
import os
from io import StringIO

# 模拟一个JSON文件内容
json_data = [
    {"城市": "上海", "AQI": 65},
    {"城市": "北京", "AQI": 120}
]
json_str = json.dumps(json_data, ensure_ascii=False)

# 模拟一个CSV文件内容
csv_data = "城市,AQI,等级\n上海,65,良\n北京,120,轻度污染"

# 为了演示,我们使用 StringIO 来模拟文件对象,避免真的读写磁盘
print("--- 模拟处理 JSON 文件 ---")
with StringIO(json_str) as f:
    city_list = json.load(f)
    print(city_list)

print("\n--- 模拟处理 CSV 文件 ---")
with StringIO(csv_data) as f:
    reader = csv.reader(f)
    for row in reader:
        print(', '.join(row))
--- 模拟处理 JSON 文件 ---
[{'城市': '上海', 'AQI': 65}, {'城市': '北京', 'AQI': 120}]

--- 模拟处理 CSV 文件 ---
城市, AQI, 等级
上海, 65, 良
北京, 120, 轻度污染

看,程序成功地区分并处理了两种格式!当你把第 40 行的 filepath 改成 '上海空气质量.csv' 时,它就会自动调用 CSV 处理函数。

5. 程序进化图:我们走到了哪一步?

让我们回顾一下这个项目的成长历程:

  • v1.0:学会了计算 AQI 的数学公式。
  • v2.0:学会了从 JSON 文件读取数据并排序输出。
  • v3.0:学会了把 JSON 数据转换成 CSV 格式并保存。
  • v4.0(本节):程序变“聪明”了! 能自动判断文件类型,并用更优雅(with)的方式处理文件。

我们的程序从一个只会算数的小计算器,变成了一个能灵活处理多种数据文件的“小管家”。

📝 动手练一练

  1. 扩展名判断增强:我们的程序目前只认识 .json 和 .csv。如果用户输入了一个 .txt 文本文件,程序会说格式不支持。请你修改一下 main() 函数中的判断部分,让它能识别 .txt 文件,并简单地用 f.read() 打印出文件的所有文本内容。

  2. 路径拼接小能手:os.path.join() 函数可以智能地拼接路径,避免手动写斜杠 / 或反斜杠 \(在不同操作系统上不一样)。例如,os.path.join('folder', 'data.json') 在 Windows 上会得到 folder\data.json,在 Mac/Linux 上会得到 folder/data.json。请你写一小段代码,假设有一个基础目录 'data' 和一个文件名 'test.csv',使用 os.path.join() 生成完整的文件路径并打印出来。

👉 点击查看第1题参考答案

思路:在 main() 函数的 if-elif-else 判断中,增加一个 elif 分支来处理 .txt 扩展名。在这个分支里,调用一个新的函数(比如 process_txt_file)来读取并打印文本文件。

# 新增的处理 txt 文件的函数
def process_txt_file(filepath):
    """处理纯文本文件"""
    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()
    print("=== 文本文件内容 ===")
    print(content)

# 在 main() 函数的判断部分增加一个分支
def main():
    filepath = 'example.txt'  # 假设这是一个文本文件
    filename, file_ext = os.path.splitext(filepath)

    if file_ext == '.json':
        process_json_file(filepath)
    elif file_ext == '.csv':
        process_csv_file(filepath)
    elif file_ext == '.txt':  # 新增的判断
        print("识别为文本文件,开始处理...")
        process_txt_file(filepath)
    else:
        print(f'不支持 {file_ext} 格式的文件!')
👉 点击查看第2题参考答案

思路:直接使用 os.path.join() 函数,传入两个字符串参数,它会返回拼接好的路径。

import os

base_dir = 'data'
filename = 'test.csv'

full_path = os.path.join(base_dir, filename)
print(f"拼接后的完整路径是:{full_path}")

# 你可以试试更多层目录
full_path2 = os.path.join('project', 'data', '2023', 'result.json')
print(f"多层目录拼接:{full_path2}")
拼接后的完整路径是:data\test.csv
多层目录拼接:project\data\2023\result.json

本章小结

恭喜!你又解锁了两个非常实用的 Python 技能:

  1. os.path.splitext():轻松获取文件扩展名,是判断文件类型的神器。
  2. with 语句:文件操作的“安全卫士”,自动管理资源的打开和关闭,代码更简洁、更健壮。

你把之前分散的 JSON 和 CSV 处理能力整合了起来,写出了一个会自己判断、自己行动的“智能”程序。这种感觉是不是很棒?

📋 行动清单

学完本节,你可以立刻:

  • 运行今天的 v4.0 程序,分别用 .json 和 .csv 文件测试它。
  • 尝试修改程序,让它支持一种新的文件格式(比如 .txt)。
  • 在你自己的其他小程序里,把文件操作的 open...close 改成 with 语句,体验一下它的简洁。

我们的空气质量数据目前还是“静态”的,是提前准备好的文件。下一节,我们要玩点更刺激的:让程序自己去网上抓取最新的、实时的空气质量数据! 这就是传说中的“网络爬虫”入门。敬请期待!

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第9章代码包:空气质量指数计算(含全部版本 10 个 .py)
    ZIP · 64KB
    下载
  • 数据集:aqi.csv(各城市 AQI 长表)
    772B
    下载
  • 数据集:beijing_aqi.json(北京监测点)
    3KB
    下载
  • 数据集:bottom10_aqi.csv(空气质量最差 10 城)
    412B
    下载
  • 数据集:china_city_aqi.csv(全国城市 AQI)
    13KB
    下载
  • 数据集:shanghai_aqi.json(上海监测点)
    3KB
    下载
  • 数据集:top10_aqi.csv(空气质量最好 10 城)
    372B
    下载
  • 数据集:top5_aqi.json(空气质量最好 5 城)
    1007B
    下载
看图文没弄懂?展开看本节视频讲解(约 11 分钟)
📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)