6.1 文件操作
6.1.1 打开文件
python
复制代码
# 基本语法
file = open(filename, mode, encoding)
# 常用模式
# 'r' - 读取(默认)
# 'w' - 写入(覆盖)
# 'a' - 追加
# 'x' - 独占创建(文件存在则失败)
# 'b' - 二进制模式
# 't' - 文本模式(默认)
# '+' - 读写模式
# 示例
file = open("test.txt", "r", encoding="utf-8")
# 使用文件
file.close() # 关闭文件
# 推荐使用with语句(自动关闭)
with open("test.txt", "r", encoding="utf-8") as file:
content = file.read()
# 离开with块时自动关闭文件
6.1.2 读取文件
python
复制代码
# 创建测试文件
with open("test.txt", "w", encoding="utf-8") as f:
f.write("第一行\n第二行\n第三行\n")
# read() - 读取全部内容
with open("test.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
# read(size) - 读取指定字符数
with open("test.txt", "r", encoding="utf-8") as f:
content = f.read(5) # 读取5个字符
print(content)
# readline() - 读取一行
with open("test.txt", "r", encoding="utf-8") as f:
line1 = f.readline()
line2 = f.readline()
print(line1, end="")
print(line2, end="")
# readlines() - 读取所有行,返回列表
with open("test.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print(lines) # ['第一行\n', '第二行\n', '第三行\n']
# 遍历文件(推荐,内存友好)
with open("test.txt", "r", encoding="utf-8") as f:
for line in f:
print(line, end="")
# 读取大文件(按块读取)
with open("large_file.txt", "r", encoding="utf-8") as f:
while True:
chunk = f.read(1024) # 每次读取1KB
if not chunk:
break
process(chunk) # 处理数据块
6.1.3 写入文件
python
复制代码
# write() - 写入字符串
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!\n")
f.write("Python Programming\n")
# writelines() - 写入字符串列表
lines = ["第一行\n", "第二行\n", "第三行\n"]
with open("output.txt", "w", encoding="utf-8") as f:
f.writelines(lines)
# 追加模式
with open("output.txt", "a", encoding="utf-8") as f:
f.write("追加的内容\n")
# print写入文件
with open("output.txt", "w", encoding="utf-8") as f:
print("Hello", file=f)
print("World", file=f)
6.1.4 文件模式详解
python
复制代码
# 文本模式 vs 二进制模式
# 文本模式('t',默认) - 处理文本文件
with open("text.txt", "r", encoding="utf-8") as f:
content = f.read() # 返回字符串
# 二进制模式('b') - 处理二进制文件(图片、视频等)
with open("image.jpg", "rb") as f:
data = f.read() # 返回bytes
# 读写模式('r+', 'w+', 'a+')
# 'r+' - 读写,文件必须存在
# 'w+' - 读写,覆盖或创建
# 'a+' - 读写,追加或创建
with open("data.txt", "w+", encoding="utf-8") as f:
f.write("Hello\n")
f.seek(0) # 移动到文件开头
content = f.read()
print(content)
# 独占创建模式('x')
try:
with open("new_file.txt", "x", encoding="utf-8") as f:
f.write("新文件")
except FileExistsError:
print("文件已存在")
6.1.5 文件指针操作
python
复制代码
with open("test.txt", "r+", encoding="utf-8") as f:
# tell() - 获取当前位置
print(f"当前位置:{f.tell()}")
# read() - 读取并移动指针
data = f.read(5)
print(f"读取内容:{data}")
print(f"当前位置:{f.tell()}")
# seek(offset, whence) - 移动指针
# whence: 0-文件开头, 1-当前位置, 2-文件末尾
f.seek(0) # 移到开头
print(f"当前位置:{f.tell()}")
f.seek(0, 2) # 移到末尾
print(f"当前位置:{f.tell()}")
6.2 目录操作
6.2.1 os模块
python
复制代码
import os
# 当前工作目录
print(os.getcwd())
# 切换目录
# os.chdir("/path/to/directory")
# 列出目录内容
files = os.listdir(".")
print(files)
# 创建目录
# os.mkdir("new_folder") # 创建单层目录
# os.makedirs("parent/child") # 递归创建
# 删除目录
# os.rmdir("new_folder") # 删除空目录
# os.removedirs("parent/child") # 递归删除空目录
# 重命名
# os.rename("old_name", "new_name")
# 删除文件
# os.remove("file.txt")
# 判断是否存在
print(os.path.exists("file.txt"))
# 判断是文件还是目录
print(os.path.isfile("file.txt"))
print(os.path.isdir("folder"))
# 路径拼接
path = os.path.join("folder", "subfolder", "file.txt")
print(path)
# 路径分割
dir_name = os.path.dirname("/home/user/file.txt") # /home/user
file_name = os.path.basename("/home/user/file.txt") # file.txt
print(dir_name, file_name)
# 获取文件大小
# size = os.path.getsize("file.txt")
# 遍历目录树
for root, dirs, files in os.walk("."):
print(f"目录:{root}")
print(f"子目录:{dirs}")
print(f"文件:{files}")
print()
6.2.2 pathlib模块(推荐,Python 3.4+)
python
复制代码
from pathlib import Path
# 创建Path对象
p = Path(".")
# 当前工作目录
print(Path.cwd())
# 主目录
print(Path.home())
# 路径拼接(使用/运算符)
path = Path("folder") / "subfolder" / "file.txt"
print(path)
# 判断存在
print(path.exists())
# 判断类型
print(path.is_file())
print(path.is_dir())
# 创建目录
# path.mkdir() # 创建单层
# path.mkdir(parents=True) # 递归创建
# 迭代目录
for item in Path(".").iterdir():
print(item)
# glob模式匹配
for py_file in Path(".").glob("*.py"):
print(py_file)
# 递归glob
for py_file in Path(".").rglob("*.py"):
print(py_file)
# 读写文件
path = Path("test.txt")
# path.write_text("Hello, World!", encoding="utf-8")
content = path.read_text(encoding="utf-8")
# 路径属性
path = Path("/home/user/file.txt")
print(path.name) # file.txt
print(path.stem) # file
print(path.suffix) # .txt
print(path.parent) # /home/user
print(path.parts) # ('/', 'home', 'user', 'file.txt')
6.3 异常处理
6.3.1 try-except基本用法
python
复制代码
# 基本语法
try:
# 可能出错的代码
result = 10 / 0
except:
# 处理异常
print("发生错误")
# 捕获特定异常
try:
num = int("abc")
except ValueError:
print("值错误:无法转换为整数")
# 捕获异常对象
try:
file = open("not_exist.txt")
except FileNotFoundError as e:
print(f"文件不存在:{e}")
# 捕获多个异常
try:
# 可能抛出多种异常的代码
num = int(input("输入数字:"))
result = 10 / num
except ValueError:
print("输入不是有效数字")
except ZeroDivisionError:
print("不能除以零")
# 使用元组捕获多个异常
try:
num = int(input("输入数字:"))
result = 10 / num
except (ValueError, ZeroDivisionError) as e:
print(f"错误:{e}")
6.3.2 try-except-else-finally
python
复制代码
# else - 没有异常时执行
try:
num = int(input("输入数字:"))
result = 10 / num
except ValueError:
print("输入错误")
except ZeroDivisionError:
print("不能除以零")
else:
print(f"结果:{result}")
# finally - 无论是否异常都执行
try:
file = open("test.txt")
content = file.read()
except FileNotFoundError:
print("文件不存在")
finally:
print("清理资源")
# file.close() # 确保文件关闭
# 完整示例
def read_file(filename):
try:
with open(filename, "r", encoding="utf-8") as f:
return f.read()
except FileNotFoundError:
print(f"文件{filename}不存在")
return None
except PermissionError:
print(f"没有权限读取{filename}")
return None
except Exception as e:
print(f"发生未知错误:{e}")
return None
else:
print("文件读取成功")
finally:
print("读取操作完成")
6.3.3 抛出异常
python
复制代码
# raise - 主动抛出异常
def divide(a, b):
if b == 0:
raise ValueError("除数不能为零")
return a / b
try:
result = divide(10, 0)
except ValueError as e:
print(f"错误:{e}")
# 重新抛出异常
try:
num = int("abc")
except ValueError as e:
print("捕获到异常,重新抛出")
raise # 重新抛出同一个异常
# 抛出不同的异常
try:
num = int("abc")
except ValueError:
raise RuntimeError("转换失败")
# 异常链
try:
result = int("abc")
except ValueError as e:
raise RuntimeError("处理失败") from e
6.3.4 常见异常类型
python
复制代码
# ValueError - 值错误
int("abc") # ValueError
# TypeError - 类型错误
"hello" + 123 # TypeError
# ZeroDivisionError - 除零错误
10 / 0 # ZeroDivisionError
# IndexError - 索引错误
[1, 2, 3][10] # IndexError
# KeyError - 键错误
{"a": 1}["b"] # KeyError
# FileNotFoundError - 文件不存在
open("not_exist.txt") # FileNotFoundError
# NameError - 名称错误
print(undefined_variable) # NameError
# AttributeError - 属性错误
"hello".non_exist_method() # AttributeError
# ImportError - 导入错误
import non_exist_module # ImportError
# RuntimeError - 运行时错误
# 通用的运行时错误
# StopIteration - 迭代器停止
it = iter([1, 2, 3])
next(it)
next(it)
next(it)
next(it) # StopIteration
# 异常层次结构
# BaseException
# ├─ Exception
# │ ├─ ValueError
# │ ├─ TypeError
# │ ├─ ZeroDivisionError
# │ ├─ IndexError
# │ ├─ KeyError
# │ ├─ FileNotFoundError
# │ └─ ...
# ├─ SystemExit
# ├─ KeyboardInterrupt
# └─ GeneratorExit
6.3.5 自定义异常
python
复制代码
# 自定义异常类
class MyError(Exception):
"""自定义异常"""
pass
class NegativeNumberError(Exception):
"""负数异常"""
def __init__(self, value):
self.value = value
self.message = f"不允许负数:{value}"
super().__init__(self.message)
# 使用自定义异常
def sqrt(x):
if x < 0:
raise NegativeNumberError(x)
return x ** 0.5
try:
result = sqrt(-1)
except NegativeNumberError as e:
print(e.message)
# 更复杂的自定义异常
class ValidationError(Exception):
"""验证错误"""
def __init__(self, field, message):
self.field = field
self.message = message
super().__init__(f"{field}: {message}")
class User:
def __init__(self, name, age):
if not name:
raise ValidationError("name", "姓名不能为空")
if age < 0:
raise ValidationError("age", "年龄不能为负数")
self.name = name
self.age = age
try:
user = User("", 25)
except ValidationError as e:
print(f"验证失败 - {e.field}: {e.message}")
6.4 上下文管理器
6.4.1 with语句
python
复制代码
# 传统方式
file = open("test.txt", "w")
try:
file.write("Hello")
finally:
file.close()
# 使用with(推荐)
with open("test.txt", "w", encoding="utf-8") as file:
file.write("Hello")
# 自动关闭文件
# 多个上下文管理器
with open("input.txt", "r") as infile, \
open("output.txt", "w") as outfile:
content = infile.read()
outfile.write(content.upper())
6.4.2 自定义上下文管理器
python
复制代码
# 方法1:使用类
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
print(f"打开文件:{self.filename}")
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"关闭文件:{self.filename}")
if self.file:
self.file.close()
# 返回True表示异常已处理,False表示继续传播异常
return False
# 使用
with FileManager("test.txt", "w") as f:
f.write("Hello")
# 方法2:使用contextlib
from contextlib import contextmanager
@contextmanager
def file_manager(filename, mode):
print(f"打开文件:{filename}")
f = open(filename, mode)
try:
yield f
finally:
print(f"关闭文件:{filename}")
f.close()
# 使用
with file_manager("test.txt", "w") as f:
f.write("Hello")
# 实用示例:数据库连接
@contextmanager
def database_connection(host, port):
print(f"连接数据库:{host}:{port}")
connection = connect_to_database(host, port)
try:
yield connection
finally:
print("关闭数据库连接")
connection.close()
# 使用
with database_connection("localhost", 3306) as conn:
# 执行数据库操作
pass
# 时间测量
from time import time
@contextmanager
def timer(name):
start = time()
yield
end = time()
print(f"{name}耗时:{end - start:.2f}秒")
# 使用
with timer("循环"):
for i in range(1000000):
pass
6.5 文件操作实战
6.5.1 读取CSV文件
python
复制代码
import csv
# 读取CSV
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.reader(f)
for row in reader:
print(row)
# 使用DictReader(推荐)
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], row["age"])
# 写入CSV
data = [
["name", "age", "city"],
["Alice", "25", "Beijing"],
["Bob", "30", "Shanghai"]
]
with open("output.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(data)
# 使用DictWriter
data = [
{"name": "Alice", "age": 25, "city": "Beijing"},
{"name": "Bob", "age": 30, "city": "Shanghai"}
]
with open("output.csv", "w", newline="", encoding="utf-8") as f:
fieldnames = ["name", "age", "city"]
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(data)
6.5.2 读取JSON文件
python
复制代码
import json
# 读取JSON
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
print(data)
# 写入JSON
data = {
"name": "Alice",
"age": 25,
"hobbies": ["reading", "music"]
}
with open("output.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
# JSON字符串转Python对象
json_str = '{"name": "Bob", "age": 30}'
data = json.loads(json_str)
print(data)
# Python对象转JSON字符串
data = {"name": "Charlie", "age": 35}
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
6.6 参考资料
官方文档
学习资源