【Python】文件处理(二)
目录
- 文件处理
- 文件与目录的属性操作
- 文件权限操作
- 文件与目录的高级操作
- 文件内容格式的操作
- JSON 文件操作
- CSV 文件操作
- Excel 文件操作
文件处理
文件与目录的属性操作
判断文件或目录是否存在
-
os.path.exists(path)
import osprint(os.path.exists("data.txt")) # True/False print(os.path.exists("folder")) # True/False
-
Path.exists()
from pathlib import Pathprint(Path("data.txt").exists()) print(Path("folder").exists())
判断文件类型
-
判断是否是文件
os.path.isfile(path)
Path.is_file()
import os from pathlib import Pathprint(os.path.isfile("data.txt")) print(Path("data.txt").is_file())
-
判断是否是目录
os.path.isdir(path)
Path.is_dir()
print(os.path.isdir("folder")) print(Path("folder").is_dir())
-
判断是否是符号链接
os.path.islink(path)
Path.is_symlink()
获取文件大小
-
os.path.getsize(path)
import ossize = os.path.getsize("data.txt") print("文件大小:", size, "字节")
-
Path.stat().st_size
from pathlib import Pathsize = Path("data.txt").stat().st_size print("文件大小:", size, "字节")
获取文件时间属性
文件常见的时间属性有三种(具体含义依系统不同略有差异):
- st_atime:最后访问时间(Access Time)
- st_mtime:最后修改时间(Modify Time,内容被修改)
- st_ctime:创建时间(Create Time,Windows);在 Unix/Linux 上可能表示元数据修改时间(Change Time)
-
用
os.path.get*
import os import timeprint("访问时间:", time.ctime(os.path.getatime("data.txt"))) print("修改时间:", time.ctime(os.path.getmtime("data.txt"))) print("创建时间:", time.ctime(os.path.getctime("data.txt")))
-
用
Path.stat()
from pathlib import Path import timep = Path("data.txt").stat()print("访问时间:", time.ctime(p.st_atime)) print("修改时间:", time.ctime(p.st_mtime)) print("创建时间:", time.ctime(p.st_ctime))
获取更多文件属性
os.stat(path)
或 Path.stat()
可以一次性获取完整信息:
import osinfo = os.stat("data.txt")
print(info.st_size) # 文件大小
print(info.st_mode) # 权限
print(info.st_uid) # 拥有者 ID(Unix)
print(info.st_gid) # 用户组 ID(Unix)
结合案例:文件信息检查工具
from pathlib import Path
import timedef file_info(path):p = Path(path)if not p.exists():print(f"{path} 不存在")returnprint("名称:", p.name)print("类型:", "目录" if p.is_dir() else "文件")print("大小:", p.stat().st_size, "字节")print("访问时间:", time.ctime(p.stat().st_atime))print("修改时间:", time.ctime(p.stat().st_mtime))print("创建时间:", time.ctime(p.stat().st_ctime))file_info("data.txt")
文件权限操作
什么是文件权限?
在操作系统里,文件通常有 读 ®、写 (w)、执行 (x) 三种权限,针对 不同的用户类别:
- u (user):文件所有者
- g (group):同组用户
- o (others):其他用户
- a (all):所有用户(user + group + others)
示例:Linux 中执行 ls -l
-rw-r--r-- 1 user group 1024 Sep 25 data.txt
解释:
rw-
→ 所有者可以读写r--
→ 同组用户只能读r--
→ 其他用户只能读
修改文件权限
-
os.chmod(path, mode)
- 作用:修改文件权限(仅限 Unix 系统有效,Windows 对执行权限的处理有限)。
- mode:用 八进制数字 表示权限,比如:
0o777
→ 所有人可读写执行0o644
→ 所有者可读写,其他人可读0o600
→ 仅所有者可读写
示例:
import os# 把 data.txt 权限改为 644 (rw-r--r--) os.chmod("data.txt", 0o644)
-
使用
stat
模块更直观stat
提供了一些常量,可以组合使用。import os, stat# 设置成 只读 os.chmod("data.txt", stat.S_IREAD)# 设置成 可写 os.chmod("data.txt", stat.S_IWRITE)# 设置成 可执行 os.chmod("script.sh", stat.S_IEXEC)# 组合权限 (读 + 写) os.chmod("config.ini", stat.S_IREAD | stat.S_IWRITE)
检查权限
os.access(path, mode)
- 作用:检查当前用户是否有权限访问某个文件。
- mode 参数:
os.F_OK
→ 文件是否存在os.R_OK
→ 是否可读os.W_OK
→ 是否可写os.X_OK
→ 是否可执行
示例:
import osprint(os.access("data.txt", os.F_OK)) # 是否存在
print(os.access("data.txt", os.R_OK)) # 是否可读
print(os.access("data.txt", os.W_OK)) # 是否可写
print(os.access("script.sh", os.X_OK)) # 是否可执行
文件所有权(Linux/Unix 常用)
在 Linux/Unix 系统中,每个文件都有 用户 ID (uid) 和 组 ID (gid)。
-
查看所有者
import osinfo = os.stat("data.txt") print("用户 ID:", info.st_uid) print("组 ID:", info.st_gid)
-
修改所有者(需要 root 权限)
import os# 把文件的所有者改为用户 ID 1000,组 ID 1000 os.chown("data.txt", 1000, 1000)
在 Windows 系统中,
os.chown()
不可用。
跨平台注意事项
- Linux/macOS:支持完整的
chmod
、chown
、权限检查。 - Windows:文件系统权限机制不同,部分操作(如
chown
、执行权限)无效。 - 如果要写跨平台代码,推荐:
- 用
os.access()
来做权限检测 - 避免依赖
chown
,Windows 不支持
- 用
综合示例:权限管理工具
import os, statdef check_permissions(path):print(f"检查 {path} 权限:")print("存在:", os.access(path, os.F_OK))print("可读:", os.access(path, os.R_OK))print("可写:", os.access(path, os.W_OK))print("可执行:", os.access(path, os.X_OK))def set_readonly(path):os.chmod(path, stat.S_IREAD)print(f"{path} 已设为只读")def set_writable(path):os.chmod(path, stat.S_IREAD | stat.S_IWRITE)print(f"{path} 已设为可写")check_permissions("data.txt")
set_readonly("data.txt")
check_permissions("data.txt")
文件与目录的高级操作
文件复制与移动(shutil
模块)
shutil
提供了更强大的文件操作接口,常用于批量处理文件。
-
复制文件
shutil.copy(src, dst)
复制文件内容 + 权限(不包含修改时间、元数据)。shutil.copy2(src, dst)
复制文件内容 + 权限 + 时间戳等元数据。
import shutil# 简单复制 shutil.copy("a.txt", "backup_a.txt")# 保留元数据复制 shutil.copy2("a.txt", "backup_with_meta.txt")
-
复制整个目录
shutil.copytree(src, dst)
递归复制目录及子目录内容。
shutil.copytree("my_folder", "backup_folder")
注意:目标目录 不能已存在,否则会报错(Python 3.8+ 可以加
dirs_exist_ok=True
来覆盖)。 -
移动文件/目录
shutil.move(src, dst)
可以移动文件或目录,相当于剪切操作。
# 移动文件 shutil.move("a.txt", "subdir/a.txt")# 移动目录 shutil.move("backup_folder", "archive/backup_folder")
删除操作
除了前面 os.remove()
和 os.rmdir()
,更常用的是 shutil
:
shutil.rmtree(path)
→ 删除整个目录树(包括所有子目录和文件)
import shutilshutil.rmtree("backup_folder") # 小心!不可逆
文件/目录信息(元数据)
有时候需要获取文件属性(大小、创建时间、修改时间等):
-
使用
os.stat()
import os import timestat_info = os.stat("a.txt")print("大小:", stat_info.st_size, "字节") print("最后修改时间:", time.ctime(stat_info.st_mtime)) print("最后访问时间:", time.ctime(stat_info.st_atime)) print("创建时间:", time.ctime(stat_info.st_ctime))
-
使用
pathlib.Path.stat()
from pathlib import Pathp = Path("a.txt") info = p.stat()print("大小:", info.st_size) print("修改时间:", info.st_mtime)
遍历目录树
如果你需要扫描所有文件,推荐用 os.walk()
或 pathlib.rglob()
:
-
os.walk()
import osfor root, dirs, files in os.walk("my_folder"):print("当前目录:", root)print("子目录:", dirs)print("文件:", files)
-
pathlib.Path.rglob()
from pathlib import Pathp = Path("my_folder")# 递归查找所有 txt 文件 for file in p.rglob("*.txt"):print(file)
路径操作(进阶)
除了前面 os.path
的 join
、split
,pathlib
提供了更优雅的方式:
from pathlib import Pathp = Path("my_folder") / "subdir" / "a.txt"print("完整路径:", p.resolve())
print("父目录:", p.parent)
print("文件名:", p.name)
print("后缀:", p.suffix)
print("是否存在:", p.exists())
临时文件与目录
有时候需要在程序运行时创建临时文件/目录,Python 提供了 tempfile
模块:
import tempfile# 创建临时文件
with tempfile.TemporaryFile(mode="w+t") as tmp:tmp.write("临时内容")tmp.seek(0)print(tmp.read()) # 程序结束后自动删除# 创建临时目录
with tempfile.TemporaryDirectory() as tmpdir:print("临时目录:", tmpdir)
压缩与解压
shutil
还支持压缩与解压(ZIP、TAR 等格式):
import shutil# 压缩目录为 zip 文件
shutil.make_archive("backup", "zip", "my_folder")# 解压缩
shutil.unpack_archive("backup.zip", "unpacked_folder")
文件内容格式的操作
JSON 文件操作
在实际开发中,JSON(JavaScript Object Notation)是最常用的数据交换格式,尤其在配置文件、前后端通信、存储结构化数据时非常常见。
Python 内置的 json
模块就能轻松读写 JSON 文件。
什么是 JSON?
- JSON 是一种 轻量级数据交换格式,结构类似 Python 的字典。
- 数据类型对应关系:
JSON 类型 | Python 类型 |
---|---|
object | dict |
array | list |
string | str |
number | int / float |
true | True |
false | False |
null | None |
读写 JSON 的基础方法
-
Python 对象 ↔ JSON 字符串
import jsondata = {"name": "Alice","age": 25,"is_student": False,"courses": ["Math", "English"],"address": {"city": "Tokyo", "zip": "100-0001"} }# Python 对象 → JSON 字符串 json_str = json.dumps(data, ensure_ascii=False, indent=4) print("JSON 字符串:\n", json_str)# JSON 字符串 → Python 对象 parsed = json.loads(json_str) print("解析后的 Python 对象:", parsed)
参数说明:
ensure_ascii=False
→ 让中文正常显示,而不是\uXXXX
形式。indent=4
→ 美化缩进,便于阅读。
-
写入 JSON 文件
# 写入 JSON 文件 with open("data.json", "w", encoding="utf-8") as f:json.dump(data, f, ensure_ascii=False, indent=4)
-
读取 JSON 文件
# 读取 JSON 文件 with open("data.json", "r", encoding="utf-8") as f:loaded_data = json.load(f)print("从文件中读取的数据:", loaded_data)
高级用法
-
处理复杂对象(自定义类)
默认情况下,
json
不能直接序列化自定义对象,需要提供 编码和解码方法。import json from datetime import datetimeclass Student:def __init__(self, name, age, enroll_date):self.name = nameself.age = ageself.enroll_date = enroll_dates = Student("Bob", 20, datetime.now())# 自定义序列化 def encode_student(obj):if isinstance(obj, Student):return {"name": obj.name, "age": obj.age, "enroll_date": obj.enroll_date.isoformat()}if isinstance(obj, datetime):return obj.isoformat()raise TypeError("类型不支持序列化")json_str = json.dumps(s, default=encode_student, ensure_ascii=False, indent=4) print(json_str)
-
反序列化回对象
def decode_student(d):if "enroll_date" in d:return Student(d["name"], d["age"], datetime.fromisoformat(d["enroll_date"]))return d# 从 JSON 恢复为 Student 对象 student_obj = json.loads(json_str, object_hook=decode_student) print(student_obj.name, student_obj.age, student_obj.enroll_date)
-
按行读取 JSON(大文件处理)
如果 JSON 文件很大,可以逐行读取,每行一个 JSON 对象(常见于日志存储)。
with open("bigdata.json", "r", encoding="utf-8") as f:for line in f:record = json.loads(line)print(record)
-
合并多个 JSON 文件
import json from pathlib import Pathmerged_data = []for file in Path("json_files").glob("*.json"):with open(file, "r", encoding="utf-8") as f:merged_data.append(json.load(f))with open("merged.json", "w", encoding="utf-8") as f:json.dump(merged_data, f, ensure_ascii=False, indent=4)
实战小案例:记事本存储 JSON
import json
from datetime import datetimeNOTE_FILE = "notes.json"def add_note(title, content):try:with open(NOTE_FILE, "r", encoding="utf-8") as f:notes = json.load(f)except FileNotFoundError:notes = []notes.append({"title": title,"content": content,"time": datetime.now().isoformat()})with open(NOTE_FILE, "w", encoding="utf-8") as f:json.dump(notes, f, ensure_ascii=False, indent=4)def show_notes():try:with open(NOTE_FILE, "r", encoding="utf-8") as f:notes = json.load(f)except FileNotFoundError:notes = []for n in notes:print(f"[{n['time']}] {n['title']}: {n['content']}")# 测试
add_note("学习 Python", "今天学了 JSON 文件操作")
show_notes()
CSV 文件操作
CSV(Comma-Separated Values,逗号分隔值)是最常见的数据存储格式之一,尤其在 数据分析、Excel 导入导出、数据库备份 等场景非常常见。
Python 提供了内置的 csv
模块 来处理 CSV 文件。
什么是 CSV?
- CSV 本质上是一个 文本文件,通过 逗号(或其他分隔符) 分隔字段。
- 常见格式:
name,age,city
Alice,25,Tokyo
Bob,30,Beijing
Charlie,22,New York
写入 CSV 文件
-
写入行数据
import csvdata = [["name", "age", "city"],["Alice", 25, "Tokyo"],["Bob", 30, "Beijing"],["Charlie", 22, "New York"] ]with open("people.csv", "w", newline="", encoding="utf-8") as f:writer = csv.writer(f)writer.writerows(data) # 写入多行
注意:
newline=""
→ 避免写入空行(Windows 特别需要)。writerow()
→ 写入单行。writerows()
→ 写入多行。
-
使用字典写入(推荐)
import csvdata = [{"name": "Alice", "age": 25, "city": "Tokyo"},{"name": "Bob", "age": 30, "city": "Beijing"},{"name": "Charlie", "age": 22, "city": "New York"} ]with open("people_dict.csv", "w", newline="", encoding="utf-8") as f:fieldnames = ["name", "age", "city"]writer = csv.DictWriter(f, fieldnames=fieldnames)writer.writeheader() # 写入表头writer.writerows(data) # 写入数据
读取 CSV 文件
-
逐行读取
import csvwith open("people.csv", "r", encoding="utf-8") as f:reader = csv.reader(f)for row in reader:print(row) # 每一行是一个列表
输出:
['name', 'age', 'city'] ['Alice', '25', 'Tokyo'] ['Bob', '30', 'Beijing'] ['Charlie', '22', 'New York']
-
使用字典方式读取
import csvwith open("people_dict.csv", "r", encoding="utf-8") as f:reader = csv.DictReader(f)for row in reader:print(row) # 每一行是一个字典
输出:
{'name': 'Alice', 'age': '25', 'city': 'Tokyo'} {'name': 'Bob', 'age': '30', 'city': 'Beijing'} {'name': 'Charlie', 'age': '22', 'city': 'New York'}
注意:所有内容会被读成字符串,需要自己转类型。
高级用法
-
自定义分隔符
有时不是逗号,而是
\t
(制表符)或;
:with open("tab_file.csv", "w", newline="", encoding="utf-8") as f:writer = csv.writer(f, delimiter="\t")writer.writerow(["name", "age", "city"])writer.writerow(["Alice", 25, "Tokyo"])
-
自定义分隔符
有时不是逗号,而是
\t
(制表符)或;
:with open("tab_file.csv", "w", newline="", encoding="utf-8") as f:writer = csv.writer(f, delimiter="\t")writer.writerow(["name", "age", "city"])writer.writerow(["Alice", 25, "Tokyo"])
-
转换为列表/字典
with open("people.csv", "r", encoding="utf-8") as f:reader = csv.reader(f)data = list(reader) # 转为列表 print(data)with open("people_dict.csv", "r", encoding="utf-8") as f:reader = csv.DictReader(f)data = list(reader) # 转为字典列表 print(data)
实战案例:成绩表统计
假设有一个 scores.csv
文件:
name,math,english,science
Alice,90,85,92
Bob,78,88,80
Charlie,95,92,89
我们计算每个人的平均分:
import csvwith open("scores.csv", "r", encoding="utf-8") as f:reader = csv.DictReader(f)for row in reader:math = int(row["math"])eng = int(row["english"])sci = int(row["science"])avg = (math + eng + sci) / 3print(f"{row['name']} 平均分: {avg:.2f}")
输出:
Alice 平均分: 89.00
Bob 平均分: 82.00
Charlie 平均分: 92.00
Excel 文件操作
安装库
如果还没有安装:
pip install openpyxl
创建 Excel 文件
from openpyxl import Workbook# 创建工作簿
wb = Workbook()# 激活默认工作表
ws = wb.active
ws.title = "学生成绩"# 写入单元格数据
ws["A1"] = "姓名"
ws["B1"] = "数学"
ws["C1"] = "英语"ws.append(["Alice", 90, 85])
ws.append(["Bob", 78, 88])
ws.append(["Charlie", 95, 92])# 保存文件
wb.save("scores.xlsx")
注意:
ws["A1"] = "姓名"
→ 直接赋值写入。ws.append([...])
→ 添加一行。
读取 Excel 文件
from openpyxl import load_workbook# 打开 Excel 文件
wb = load_workbook("scores.xlsx")# 获取工作表
ws = wb["学生成绩"]# 遍历行
for row in ws.iter_rows(values_only=True):print(row)
输出:
('姓名', '数学', '英语')
('Alice', 90, 85)
('Bob', 78, 88)
('Charlie', 95, 92)
获取单元格信息
# 获取单个单元格
cell = ws["B2"]
print("值:", cell.value)
print("行:", cell.row, "列:", cell.column)# 遍历列
for col in ws.iter_cols(min_col=2, max_col=3, values_only=True):print(col)
修改 Excel
# 修改单元格
ws["C2"] = 95 # 把 Alice 的英语改成 95# 插入新行
ws.insert_rows(2)# 删除列
ws.delete_cols(2)wb.save("scores_updated.xlsx")
样式设置(美化表格)
from openpyxl.styles import Font, Alignment, PatternFill# 设置字体
ws["A1"].font = Font(bold=True, color="FFFFFF")# 设置背景色
ws["A1"].fill = PatternFill(start_color="4F81BD", end_color="4F81BD", fill_type="solid")# 居中对齐
ws["A1"].alignment = Alignment(horizontal="center", vertical="center")wb.save("scores_styled.xlsx")
多个工作表操作
# 新建工作表
ws2 = wb.create_sheet("总分")# 写入数据
ws2["A1"] = "姓名"
ws2["B1"] = "总分"# 从学生成绩表读取并计算总分
for row in ws.iter_rows(min_row=2, values_only=True):name, math, english = rowws2.append([name, math + english])wb.save("scores_with_total.xlsx")
实战案例:统计成绩并排序
from openpyxl import load_workbookwb = load_workbook("scores.xlsx")
ws = wb.active# 提取数据
data = []
for row in ws.iter_rows(min_row=2, values_only=True):name, math, english = rowtotal = math + englishdata.append((name, math, english, total))# 排序(按总分降序)
data.sort(key=lambda x: x[3], reverse=True)# 写入新表
ws_sorted = wb.create_sheet("排序结果")
ws_sorted.append(["姓名", "数学", "英语", "总分"])
for row in data:ws_sorted.append(row)wb.save("scores_sorted.xlsx")
高级功能(常用扩展)
- 公式支持:
ws["D2"] = "=B2+C2"
(Excel 会自动计算) - 合并单元格:
ws.merge_cells("A1:C1")
- 冻结窗格:
ws.freeze_panes = "A2"
(冻结第一行) - 自动调整列宽:需手动计算字符串长度,再设置
column_dimensions
。