目录
- 文件读取操作
- 读取文件的全部内容
- 相对路径和绝对路径
- 逐行访问文件内容
- 文件写入操作
- 写入单行内容
- 写入多行内容
- 结构化数据的存储
- 异常处理机制
- 理解异常的工作原理
- ZeroDivisionError异常示例
- try-except语句块的使用
- else语句块的正确使用
- 静默失败的合理应用
本文将深入探讨Python中的文件处理技术,帮助开发者构建能够高效处理大量数据的程序。同时,我们还将重点介绍异常处理机制,确保程序在面对意外情况时能够优雅地处理错误而不是崩溃。此外,还将学习如何使用json模块持久化存储用户数据,防止程序结束运行后数据丢失。
文件读取操作
在数据分析和处理应用中,文件读取是最基础也是最重要的操作之一。无论是分析日志文件、处理配置信息还是读取数据集,掌握文件读取技术都是必不可少的。
读取文件的全部内容
Python提供了 pathlib
模块来优雅地处理文件路径操作。相比传统的 os.path
方式,pathlib
提供了更加面向对象和直观的接口。
from pathlib import Path# 创建Path对象指向目标文件
file_path = Path('data/sample.txt')# 读取文件全部内容
try:content = file_path.read_text(encoding='utf-8')print(f"文件内容长度:{len(content)} 字符")
except FileNotFoundError:print(f"文件 {file_path} 不存在")
read_text()
方法会一次性读取整个文件内容并返回字符串对象。建议在读取文件时显式指定编码格式,避免因编码问题导致的乱码。
相对路径和绝对路径
理解路径概念对于文件操作至关重要:
- 相对路径: 相对于当前工作目录的路径,便于项目迁移和部署
- 绝对路径: 文件在文件系统中的完整路径,具有唯一性
from pathlib import Path# 相对路径示例
relative_path = Path('config/settings.json')# 绝对路径示例
absolute_path = Path('/home/user/projects/data/input.csv')# 获取当前工作目录
current_dir = Path.cwd()
print(f"当前工作目录:{current_dir}")# 将相对路径转换为绝对路径
abs_path = relative_path.resolve()
print(f"绝对路径:{abs_path}")
逐行访问文件内容
对于大型文件,逐行处理能够有效控制内存使用:
from pathlib import Pathfile_path = Path('logs/application.log')try:content = file_path.read_text(encoding='utf-8')lines = content.splitlines()# 逐行处理for line_num, line in enumerate(lines, 1):if 'ERROR' in line:print(f"第{line_num}行发现错误:{line.strip()}")except FileNotFoundError:print("日志文件不存在")
文件写入操作
文件写入是数据持久化的重要手段,Python提供了多种写入方式来满足不同需求。
写入单行内容
from pathlib import Pathoutput_path = Path('output/result.txt')# 确保目录存在
output_path.parent.mkdir(parents=True, exist_ok=True)# 写入单行内容
message = "数据处理完成,共处理1000条记录"
output_path.write_text(message, encoding='utf-8')
写入多行内容
from pathlib import Pathreport_path = Path('reports/daily_summary.txt')# 准备多行内容
lines = ["=== 每日数据处理报告 ===","处理日期:2024-01-15","总记录数:5000","成功处理:4950","失败记录:50","处理耗时:120秒"
]# 写入多行内容
content = '\n'.join(lines)
report_path.write_text(content, encoding='utf-8')
结构化数据的存储
在实际开发中,经常需要存储列表、字典等复杂数据结构。JSON格式因其轻量级和跨平台特性成为首选方案:
import json
from pathlib import Path# 存储字典数据
user_data = {"users": [{"id": 1, "name": "张三", "email": "zhangsan@example.com"},{"id": 2, "name": "李四", "email": "lisi@example.com"}],"total": 2,"last_updated": "2024-01-15T10:30:00"
}data_path = Path('data/users.json')# 使用json.dumps()序列化并写入文件
try:with open(data_path, 'w', encoding='utf-8') as f:json.dump(user_data, f, ensure_ascii=False, indent=2)print("数据保存成功")
except IOError as e:print(f"文件写入失败:{e}")# 读取JSON数据
try:with open(data_path, 'r', encoding='utf-8') as f:loaded_data = json.load(f)print(f"加载了 {loaded_data['total']} 个用户记录")
except (FileNotFoundError, json.JSONDecodeError) as e:print(f"数据加载失败:{e}")
- json.dump() 函数说明:
f
:文件类对象,f 表示 fileensure_ascii=False
:不要将所有内容都转换为ASCII字符indent=2
:默认为None
,即所有 JSON 字符会被压缩成一行,没有多余的空格和换行。
异常处理机制
异常处理是构建健壮应用程序的核心技术。Python通过异常对象来封装错误信息,并提供了完善的异常处理机制。
理解异常的工作原理
当程序遇到错误时,Python解释器会创建一个异常对象,包含错误类型、错误信息和发生位置等详细信息。如果异常未被捕获,程序将终止并显示 traceback
信息。
ZeroDivisionError异常示例
def calculate_average(numbers):"""计算数字列表的平均值"""if not numbers:raise ValueError("输入列表不能为空")try:total = sum(numbers)count = len(numbers)average = total / countreturn averageexcept ZeroDivisionError:print("错误:除零操作")return Noneexcept TypeError as e:print(f"错误:数据类型不正确 - {e}")return None# 测试用例
test_data = [10, 20, 30, 40]
result = calculate_average(test_data)
print(f"平均值:{result}")
try-except语句块的使用
try-except
语句块提供了结构化的异常处理方式:
from pathlib import Path
import jsondef load_config(config_path):"""加载配置文件"""try:path = Path(config_path)content = path.read_text(encoding='utf-8')config = json.loads(content)return configexcept FileNotFoundError:print(f"配置文件 {config_path} 不存在")return {}except json.JSONDecodeError as e:print(f"配置文件格式错误:{e}")return {}except PermissionError:print("没有权限访问配置文件")return {}except Exception as e:print(f"未知错误:{e}")return {}# 使用示例
config = load_config('config/app.json')
else语句块的正确使用
else
语句块只有在 try
块成功执行且没有异常时才会执行,适合放置依赖于 try
块成功执行的代码:
def process_file(file_path):"""处理文件并生成报告"""try:path = Path(file_path)content = path.read_text(encoding='utf-8')lines = content.splitlines()except FileNotFoundError:print(f"文件 {file_path} 不存在")except PermissionError:print("没有文件访问权限")else:# 只有文件成功读取后才执行此部分print(f"文件读取成功,共 {len(lines)} 行")# 生成处理报告report = {"file_path": str(file_path),"total_lines": len(lines),"non_empty_lines": len([line for line in lines if line.strip()]),"processed_at": "2024-01-15T10:30:00"}# 保存报告report_path = Path('reports/processing_report.json')with open(report_path, 'w', encoding='utf-8') as f:json.dump(report, f, ensure_ascii=False, indent=2)print("处理报告已生成")
静默失败的合理应用
在某些场景下,我们希望程序在遇到特定异常时继续运行而不显示错误信息。这种做法称为"静默失败",但应该谨慎使用:
import json
from pathlib import Pathdef load_user_preferences(user_id):"""加载用户偏好设置,如果失败则返回默认设置"""pref_file = Path(f'preferences/user_{user_id}.json')try:with open(pref_file, 'r', encoding='utf-8') as f:preferences = json.load(f)except (FileNotFoundError, json.JSONDecodeError, PermissionError):# 静默处理异常,返回默认设置preferences = {"theme": "light","language": "zh-CN","notifications": True}return preferences# 静默失败适用场景:
# 1. 配置文件不存在时使用默认配置
# 2. 可选功能失败时不影响主要功能
# 3. 日志记录失败时不中断业务流程# 注意:即使是静默失败,也应该在适当的地方记录日志
def safe_log_action(action, user_id):"""安全记录用户操作,失败时不影响主业务"""try:log_entry = {"timestamp": "2024-01-15T10:30:00","user_id": user_id,"action": action}log_path = Path('logs/user_actions.json')# 读取现有日志if log_path.exists():with open(log_path, 'r', encoding='utf-8') as f:logs = json.load(f)else:logs = []# 添加新日志并保存logs.append(log_entry)with open(log_path, 'w', encoding='utf-8') as f:json.dump(logs, f, ensure_ascii=False, indent=2)except Exception:# 静默失败,但在生产环境中应该记录到系统日志pass # 日志记录失败不应影响主要业务逻辑
通过掌握这些文件处理和异常处理技术,你将能够构建更加健壮和可靠的Python应用程序。
2025.09 宣武门