python 文件操作与异常处理-之九
·
第9:文件操作与异常处理
目录
文件操作基础
文件操作是程序与外部存储交互的重要方式,Python提供了丰富的文件操作功能。
文件操作模式
# 文件打开模式
# 'r' - 只读模式(默认)
# 'w' - 写入模式(覆盖原文件)
# 'a' - 追加模式
# 'x' - 独占创建模式
# 'b' - 二进制模式
# 't' - 文本模式(默认)
# '+' - 读写模式
# 常见组合
# 'rt' 或 'r' - 文本只读
# 'wt' 或 'w' - 文本写入
# 'rb' - 二进制只读
# 'wb' - 二进制写入
# 'r+' - 文本读写
# 'w+' - 文本读写(覆盖)
# 'a+' - 文本读写(追加)
文件打开与关闭
正确打开和关闭文件是文件操作的基础。
基本文件操作
# 打开文件
file = open("example.txt", "r", encoding="utf-8")
# 读取文件内容
content = file.read()
# 关闭文件
file.close()
# 检查文件是否关闭
print(file.closed) # 输出:True
文件对象属性
file = open("example.txt", "r", encoding="utf-8")
print(file.name) # 文件名
print(file.mode) # 打开模式
print(file.encoding) # 编码方式
file.close()
文件读取
Python提供了多种读取文件内容的方法。
read() 方法
# 读取整个文件
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read()
print(content)
# 读取指定字符数
with open("example.txt", "r", encoding="utf-8") as file:
chunk = file.read(10) # 读取前10个字符
print(chunk)
readline() 方法
# 逐行读取
with open("example.txt", "r", encoding="utf-8") as file:
line1 = file.readline() # 读取第一行
line2 = file.readline() # 读取第二行
print(f"第一行:{line1}")
print(f"第二行:{line2}")
# 读取指定字符数的一行
with open("example.txt", "r", encoding="utf-8") as file:
partial_line = file.readline(5) # 读取一行的前5个字符
print(partial_line)
readlines() 方法
# 读取所有行到列表
with open("example.txt", "r", encoding="utf-8") as file:
lines = file.readlines()
for i, line in enumerate(lines, 1):
print(f"第{i}行:{line.strip()}") # strip()去除换行符
迭代器方式读取
# 最推荐的方式:使用迭代器逐行读取
with open("example.txt", "r", encoding="utf-8") as file:
for line_num, line in enumerate(file, 1):
print(f"第{line_num}行:{line.strip()}")
文件写入
文件写入操作允许我们创建和修改文件内容。
write() 方法
# 写入文本
with open("output.txt", "w", encoding="utf-8") as file:
file.write("Hello, World!\n")
file.write("这是第二行内容\n")
# 写入多行
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("output.txt", "w", encoding="utf-8") as file:
file.writelines(lines)
追加模式
# 追加内容到文件末尾
with open("output.txt", "a", encoding="utf-8") as file:
file.write("这是追加的内容\n")
格式化写入
# 格式化写入数据
data = [
{"name": "张三", "age": 25, "city": "北京"},
{"name": "李四", "age": 30, "city": "上海"},
{"name": "王五", "age": 35, "city": "广州"}
]
with open("users.txt", "w", encoding="utf-8") as file:
file.write("姓名\t年龄\t城市\n")
file.write("-" * 20 + "\n")
for user in data:
file.write(f"{user['name']}\t{user['age']}\t{user['city']}\n")
文件定位
文件定位允许我们在文件中移动读写位置。
seek() 和 tell() 方法
with open("example.txt", "r", encoding="utf-8") as file:
# 获取当前位置
print(f"当前位置:{file.tell()}") # 输出:0
# 读取一些内容
content = file.read(10)
print(f"读取内容:{content}")
print(f"当前位置:{file.tell()}") # 输出:10
# 移动到文件开头
file.seek(0)
print(f"当前位置:{file.tell()}") # 输出:0
# 移动到指定位置
file.seek(5)
content = file.read(5)
print(f"从位置5读取:{content}")
文件指针操作
# 相对定位
with open("example.txt", "r", encoding="utf-8") as file:
file.seek(10) # 绝对定位到位置10
file.seek(5, 0) # 从文件开头移动5个字节
file.seek(5, 1) # 从当前位置移动5个字节
file.seek(-5, 2) # 从文件末尾倒数5个字节
目录操作
Python的os和pathlib模块提供了目录操作功能。
os模块目录操作
import os
# 获取当前工作目录
current_dir = os.getcwd()
print(f"当前目录:{current_dir}")
# 切换目录
# os.chdir("/path/to/directory")
# 列出目录内容
files = os.listdir(".")
print(f"当前目录文件:{files}")
# 创建目录
# os.mkdir("new_directory") # 创建单级目录
# os.makedirs("parent/child") # 创建多级目录
# 删除目录
# os.rmdir("empty_directory") # 删除空目录
# os.removedirs("parent/child") # 删除多级空目录
# 检查路径是否存在
if os.path.exists("example.txt"):
print("文件存在")
# 检查是否为文件或目录
if os.path.isfile("example.txt"):
print("这是一个文件")
if os.path.isdir("documents"):
print("这是一个目录")
pathlib模块(推荐)
from pathlib import Path
# 创建路径对象
path = Path("example.txt")
# 检查文件是否存在
if path.exists():
print("文件存在")
# 检查是否为文件
if path.is_file():
print("这是一个文件")
# 检查是否为目录
if path.is_dir():
print("这是一个目录")
# 获取文件信息
if path.exists():
stat = path.stat()
print(f"文件大小:{stat.st_size} 字节")
print(f"修改时间:{stat.st_mtime}")
# 列出目录内容
current_path = Path(".")
for item in current_path.iterdir():
if item.is_file():
print(f"文件:{item}")
elif item.is_dir():
print(f"目录:{item}")
# 创建目录
# new_dir = Path("new_directory")
# new_dir.mkdir(exist_ok=True) # exist_ok=True避免目录已存在时的错误
# 路径操作
data_path = Path("data") / "users" / "profiles.txt"
print(f"完整路径:{data_path}")
异常处理基础
异常处理允许程序优雅地处理运行时错误。
try-except语句
# 基本异常处理
try:
result = 10 / 0
except ZeroDivisionError:
print("不能除以零")
# 捕获多种异常
try:
number = int(input("请输入一个数字:"))
result = 10 / number
print(f"结果:{result}")
except ValueError:
print("请输入有效的数字")
except ZeroDivisionError:
print("不能除以零")
except Exception as e:
print(f"发生了未知错误:{e}")
else和finally子句
# else子句:没有异常时执行
# finally子句:无论是否有异常都会执行
try:
file = open("example.txt", "r", encoding="utf-8")
content = file.read()
except FileNotFoundError:
print("文件未找到")
except Exception as e:
print(f"读取文件时发生错误:{e}")
else:
print("文件读取成功")
print(f"文件内容:{content}")
finally:
try:
file.close()
print("文件已关闭")
except:
pass
异常信息获取
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"异常类型:{type(e).__name__}")
print(f"异常信息:{e}")
print(f"异常参数:{e.args}")
常见异常类型
Python提供了多种内置异常类型。
内置异常类型
# 常见异常类型示例
exceptions_examples = [
# ValueError - 值错误
("int('abc')", ValueError),
# TypeError - 类型错误
("'hello' + 5", TypeError),
# IndexError - 索引错误
("[1, 2, 3][5]", IndexError),
# KeyError - 键错误
("{'a': 1}['b']", KeyError),
# FileNotFoundError - 文件未找到
("open('nonexistent.txt')", FileNotFoundError),
# ZeroDivisionError - 除零错误
("10 / 0", ZeroDivisionError),
# AttributeError - 属性错误
("'hello'.nonexistent_method()", AttributeError)
]
# 演示异常处理
def demonstrate_exceptions():
try:
# 触发ValueError
int("abc")
except ValueError as e:
print(f"ValueError: {e}")
try:
# 触发IndexError
[1, 2, 3][5]
except IndexError as e:
print(f"IndexError: {e}")
try:
# 触发KeyError
{"a": 1}["b"]
except KeyError as e:
print(f"KeyError: {e}")
demonstrate_exceptions()
自定义异常
我们可以创建自定义异常类型来处理特定的错误情况。
创建自定义异常
# 定义自定义异常类
class CustomError(Exception):
"""自定义异常基类"""
pass
class ValidationError(CustomError):
"""验证错误"""
def __init__(self, message, error_code=None):
super().__init__(message)
self.error_code = error_code
class NetworkError(CustomError):
"""网络错误"""
pass
# 使用自定义异常
def validate_age(age):
"""验证年龄"""
if age < 0:
raise ValidationError("年龄不能为负数", error_code="NEGATIVE_AGE")
elif age > 150:
raise ValidationError("年龄不能超过150岁", error_code="INVALID_AGE")
return True
# 处理自定义异常
try:
validate_age(-5)
except ValidationError as e:
print(f"验证失败:{e}")
if hasattr(e, 'error_code'):
print(f"错误代码:{e.error_code}")
上下文管理器
上下文管理器确保资源得到正确管理,即使发生异常。
with语句
# 文件操作的上下文管理
with open("example.txt", "r", encoding="utf-8") as file:
content = file.read()
# 文件会自动关闭,即使发生异常
# 等价的传统方式
file = open("example.txt", "r", encoding="utf-8")
try:
content = file.read()
finally:
file.close() # 确保文件被关闭
自定义上下文管理器
# 使用类实现上下文管理器
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
print("打开文件")
self.file = open(self.filename, self.mode, encoding="utf-8")
return self.file
def __exit__(self, exc_type, exc_value, exc_traceback):
print("关闭文件")
if self.file:
self.file.close()
# 返回False表示不抑制异常
return False
# 使用自定义上下文管理器
with FileManager("example.txt", "r") as file:
content = file.read()
print(content)
# 使用contextlib装饰器
from contextlib import contextmanager
@contextmanager
def database_connection():
print("连接数据库")
try:
# 模拟数据库连接
connection = "database_connection"
yield connection
finally:
print("关闭数据库连接")
# 使用contextmanager
with database_connection() as conn:
print(f"使用连接:{conn}")
日志记录
日志记录是跟踪程序运行状态的重要工具。
logging模块基础
import logging
# 配置日志
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log', encoding='utf-8'),
logging.StreamHandler()
]
)
# 创建日志记录器
logger = logging.getLogger(__name__)
# 不同级别的日志
logger.debug("这是调试信息")
logger.info("这是普通信息")
logger.warning("这是警告信息")
logger.error("这是错误信息")
logger.critical("这是严重错误信息")
日志处理
import logging
# 创建日志记录器
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 创建文件处理器
file_handler = logging.FileHandler('app.log', encoding='utf-8')
file_handler.setLevel(logging.INFO)
# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
# 创建格式化器
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 添加处理器到记录器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 使用日志
logger.debug("调试信息")
logger.info("应用程序启动")
logger.warning("这是一个警告")
logger.error("发生错误")
实际应用示例
import os
import json
import csv
import logging
from pathlib import Path
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 文件备份工具
class FileBackup:
"""文件备份工具"""
def __init__(self, source_dir, backup_dir):
self.source_dir = Path(source_dir)
self.backup_dir = Path(backup_dir)
self.backup_dir.mkdir(exist_ok=True)
def backup_files(self):
"""备份文件"""
try:
if not self.source_dir.exists():
raise FileNotFoundError(f"源目录不存在:{self.source_dir}")
backed_up = 0
for file_path in self.source_dir.rglob("*"):
if file_path.is_file():
self._backup_file(file_path)
backed_up += 1
logger.info(f"成功备份 {backed_up} 个文件")
return backed_up
except Exception as e:
logger.error(f"备份过程中发生错误:{e}")
raise
def _backup_file(self, file_path):
"""备份单个文件"""
try:
# 计算相对路径
relative_path = file_path.relative_to(self.source_dir)
backup_path = self.backup_dir / relative_path
# 创建目录
backup_path.parent.mkdir(parents=True, exist_ok=True)
# 复制文件
with open(file_path, 'rb') as src, open(backup_path, 'wb') as dst:
dst.write(src.read())
logger.debug(f"已备份:{file_path} -> {backup_path}")
except Exception as e:
logger.error(f"备份文件 {file_path} 时发生错误:{e}")
raise
# 配置文件管理器
class ConfigManager:
"""配置文件管理器"""
def __init__(self, config_file="config.json"):
self.config_file = Path(config_file)
self.config = {}
self.load_config()
def load_config(self):
"""加载配置"""
try:
if self.config_file.exists():
with open(self.config_file, 'r', encoding='utf-8') as f:
self.config = json.load(f)
logger.info("配置文件加载成功")
else:
logger.warning("配置文件不存在,使用默认配置")
self.config = self._get_default_config()
except json.JSONDecodeError as e:
logger.error(f"配置文件格式错误:{e}")
self.config = self._get_default_config()
except Exception as e:
logger.error(f"加载配置文件时发生错误:{e}")
self.config = self._get_default_config()
def save_config(self):
"""保存配置"""
try:
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(self.config, f, ensure_ascii=False, indent=2)
logger.info("配置文件保存成功")
except Exception as e:
logger.error(f"保存配置文件时发生错误:{e}")
raise
def get(self, key, default=None):
"""获取配置值"""
return self.config.get(key, default)
def set(self, key, value):
"""设置配置值"""
self.config[key] = value
def _get_default_config(self):
"""获取默认配置"""
return {
"app_name": "MyApp",
"version": "1.0.0",
"debug": False,
"max_connections": 100
}
# CSV数据处理器
class CSVProcessor:
"""CSV数据处理器"""
def __init__(self, csv_file):
self.csv_file = Path(csv_file)
def read_csv(self):
"""读取CSV文件"""
try:
data = []
with open(self.csv_file, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
data.append(row)
return data
except FileNotFoundError:
logger.error(f"CSV文件不存在:{self.csv_file}")
raise
except Exception as e:
logger.error(f"读取CSV文件时发生错误:{e}")
raise
def write_csv(self, data, fieldnames):
"""写入CSV文件"""
try:
with open(self.csv_file, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(data)
logger.info(f"CSV文件写入成功:{self.csv_file}")
except Exception as e:
logger.error(f"写入CSV文件时发生错误:{e}")
raise
def filter_data(self, data, condition):
"""过滤数据"""
return [row for row in data if condition(row)]
# 使用示例
def main():
"""主函数示例"""
try:
# 配置管理
config = ConfigManager("app_config.json")
config.set("debug", True)
config.save_config()
print(f"应用名称:{config.get('app_name')}")
print(f"调试模式:{config.get('debug')}")
# CSV处理
sample_data = [
{"name": "张三", "age": "25", "city": "北京"},
{"name": "李四", "age": "30", "city": "上海"},
{"name": "王五", "age": "35", "city": "广州"}
]
csv_processor = CSVProcessor("users.csv")
csv_processor.write_csv(sample_data, ["name", "age", "city"])
# 读取并过滤数据
data = csv_processor.read_csv()
young_people = csv_processor.filter_data(
data,
lambda row: int(row["age"]) < 30
)
print("年龄小于30的用户:")
for person in young_people:
print(f" {person['name']} - {person['age']}岁")
# 文件备份
backup = FileBackup(".", "backup")
count = backup.backup_files()
print(f"备份了 {count} 个文件")
except Exception as e:
logger.error(f"程序执行过程中发生错误:{e}")
raise
if __name__ == "__main__":
main()
总结
本篇教程详细介绍了Python中的文件操作和异常处理。我们学习了文件的读写操作、目录管理、异常处理机制、自定义异常、上下文管理器和日志记录等重要内容。
更多推荐

所有评论(0)