欢迎光临
我们一直在努力

Python 文件操作与异常处理专项练习:6 道编程题从入门到精通

配套专栏:Python 全栈修炼之路 第 08 篇《文件操作与异常处理》

难度分布:⭐ → ⭐⭐ → ⭐⭐ → ⭐⭐⭐ → ⭐⭐⭐ → ⭐⭐⭐⭐

核心覆盖:文件读写、with 上下文管理器、pathlib、异常处理、日志记录、JSON/YAML 配置、目录遍历


题目一:安全的文件复制工具 ⭐

📌 题目描述

编写函数 safe_copy(src, dst, overwrite=False),实现安全的文件复制功能:

# 基础用法
safe_copy(\’data.txt\’, \’backup/data.txt\’) # 复制到备份目录

# 显示进度
safe_copy(\’large.zip\’, \’backup/large.zip\’, progress=True)
# 输出: 复制进度: 45.2%

# 处理异常
safe_copy(\’not_exist.txt\’, \’dest.txt\’) # 源文件不存在,抛出 FileNotFoundError
safe_copy(\’src.txt\’, \’dest.txt\’, overwrite=False) # 目标已存在,抛出 FileExistsError

💡 编程思路

这道题考察 文件读写 + 异常处理 + 目录创建:

  • 路径处理:使用 pathlib.Path 统一处理路径,自动创建目标目录的父目录。
  • 安全检查:检查源文件是否存在、目标文件是否已存在(根据 overwrite 参数决定是否覆盖)。
  • 分块复制:对于大文件,使用 shutil.copyfileobj 或手动分块读取写入,避免一次性加载到内存。
  • 进度显示:计算文件总大小,每复制一定字节数更新进度百分比。
  • 🖥️ 参考代码

    from pathlib import Path
    import shutil

    def safe_copy(src, dst, overwrite=False, progress=False, chunk_size=8192):
    \”\”\”
    安全的文件复制工具

    参数:
    src: 源文件路径
    dst: 目标文件路径
    overwrite: 是否覆盖已存在的目标文件
    progress: 是否显示复制进度
    chunk_size: 分块大小(字节)

    异常:
    FileNotFoundError: 源文件不存在
    FileExistsError: 目标文件已存在且 overwrite=False
    PermissionError: 权限不足
    \”\”\”
    src_path = Path(src)
    dst_path = Path(dst)

    # 检查源文件
    if not src_path.exists():
    raise FileNotFoundError(f\”源文件不存在: {

    src}\”)
    if not src_path.is_file():
    raise ValueError(f\”源路径不是文件: {

    src}\”)

    # 检查目标文件
    if dst_path.exists() and not overwrite:
    raise FileExistsError(f\”目标文件已存在: {

    dst} (使用 overwrite=True 覆盖)\”)

    # 创建目标目录
    dst_path.parent.mkdir(parents=True, exist_ok=True)

    # 获取文件大小用于进度计算
    total_size = src_path.stat().st_size
    copied_size = 0

    # 分块复制
    with open(src_path, \’rb\’) as fsrc:
    with open(dst_path, \’wb\’) as fdst:
    while True:
    chunk = fsrc.read(chunk_size)
    if not chunk:
    break

    fdst.write(chunk)
    copied_size += len(chunk)

    if progress and total_size > 0:
    percent = (copied_size / total_size) * 100
    print(f\”\\r复制进度: {

    percent:.1f}%\”, end=\’\’, flush=True)

    if progress:
    print() # 换行

    return dst_path

    def copy_with_metadata(src, dst, overwrite=False):
    \”\”\”复制文件并保留元数据(修改时间、权限等)\”\”\”
    dst_path = safe_copy(src, dst, overwrite)

    # 复制元数据
    src_stat = Path(src).stat()
    dst_path.touch()
    import os
    os.utime(dst_path, (src_stat.st_atime, src_stat.st_mtime))

    return dst_path

    # 测试
    if __name__ == \”__main__\”:
    import tempfile
    import os

    # 创建临时测试文件
    with tempfile.NamedTemporaryFile(mode=\’w\’, delete=False, suffix=\’.txt\’) as f:
    f.write(\”Hello, World!\” * 1000)
    temp_src = f.name

    try:
    # 基础复制
    temp_dst = tempfile.mktemp(suffix=\’.txt\’)
    result = safe_copy(temp_src, temp_dst)
    print(f\”复制成功: {

    result}\”)
    assert Path(temp_dst).read_text() == Path(temp_src).read_text()

    # 测试覆盖检查
    try:
    safe_copy(temp_src, temp_dst, overwrite=False)
    assert False, \”应该抛出 FileExistsError\”
    except FileExistsError:
    print(\”覆盖检查通过 ✓\”)

    # 测试源文件不存在
    try:
    safe_copy(\’not_exist_xxx.txt\’, \’dest.txt\’)
    assert False, \”应该抛出 FileNotFoundError\”
    except FileNotFoundError:
    print(\”源文件检查通过 ✓\”)

    # 清理
    os.unlink(temp_dst)

    finally:
    os.unlink(temp_src)

    print(\”\\n所有测试通过 ✓\”)

    🔗 关联知识点

    知识点
    说明
    pathlib.Path 面向对象的路径操作
    mkdir(parents=True) 自动创建父目录
    with open(…) 上下文管理器确保文件关闭
    分块读取 read(chunk_size) 大文件处理,避免内存溢出
    自定义异常抛出 raise FileNotFoundError(…)

    题目二:JSON 配置文件管理器 ⭐⭐

    📌 题目描述

    实现一个 ConfigManager 类,管理 JSON 格式的配置文件:

    config = ConfigManager(\’app.json\’)

    # 使用点号分隔的键路径
    config.set(\’database.host\’, \’localhost\’)
    config.set(\’database.port\’, 3306)
    config.set(\’database.credentials.username\’, \’admin\’)

    # 获取值(支持默认值)
    host = config.get(\’database.host\’) # \’localhost\’
    ssl = config.get(\’database.ssl\’, False) # False(默认值)

    # 保存到文件
    config.save()

    # 加载已存在的配置
    config2 = ConfigManager(\’app.json\’)
    print(config2.get(\’database.port\’)) # 3306

    💡 编程思路

    这道题考察 JSON 读写 + 嵌套字典操作 + 异常处理:

  • 点号路径解析:将 \’database.host\’ 拆分为 [\’database\’, \’host\’],逐级访问或创建嵌套字典。
  • 自动创建中间层级:如果 \’database\’ 不存在,自动创建空字典。
  • 异常处理:文件不存在时返回空配置,JSON 格式错误时抛出友好的异常信息。
  • 类型保持:JSON 支持字符串、数字、布尔、列表、字典等类型,读写时保持类型不变。
  • 🖥️ 参考代码

    import json
    from pathlib import Path

    class ConfigError(Exception):
    \”\”\”配置相关错误\”\”\”
    pass

    class ConfigManager:
    \”\”\”JSON 配置文件管理器\”\”\”

    def __init__(self, config_path):
    self.config_path = Path(config_path)
    self._config = {

    }
    self._load()

    def _load(self):
    \”\”\”从文件加载配置\”\”\”
    try:
    if self.config_path.exists():
    with open(self.config_path, \’r\’, encoding=\’utf-8\’) as f:
    self._config = json.load(f)
    else:
    self._config = {

    }
    except json.JSONDecodeError as e:
    raise ConfigError(f\”配置文件格式错误: {

    e}\”) from e
    except PermissionError as e:
    raise ConfigError(f\”无法读取配置文件: {

    e}\”) from e

    def get(self, key, default=None):
    \”\”\”
    获取配置值

    参数:
    key: 点号分隔的键路径,如 \’database.host\’
    default: 键不存在时返回的默认值
    \”\”\”
    keys = key.split(\’.\’)
    value = self._config

    for k in keys:
    if isinstance(value, dict) and k in value:
    value = value[k]
    else:
    return default

    return value

    def set(self, key, value):
    \”\”\”
    设置配置值

    参数:
    key: 点号分隔的键路径
    value: 要设置的值
    \”\”\”
    keys = key.split(\’.\’)
    config = self._config

    # 创建中间层级
    for k in keys[:1]:
    if k not in config:
    config[k] = {

    }
    elif not isinstance(config[k], dict):
    raise ConfigError(f\”无法设置 \’{

    key}\’: \’{

    k}\’ 不是字典\”)
    config = config[k]

    config[keys[1]] = value

    def delete(self, key):
    \”\”\”删除配置项\”\”\”
    keys = key.split(\’.\’)
    config = self._config

    for k in keys[:1]:
    if k not in config or not isinstance(config[k], dict):
    return False
    config = config[k]

    if keys[1] in config:
    del config[keys[1]]
    return True
    return False

    def save(self, indent=2):
    \”\”\”保存配置到文件\”\”\”
    try:
    self.config_path.parent.mkdir(parents=True, exist_ok=True)
    with open(self.config_path, \’w\’, encoding=\’utf-8\’) as f:
    json.dump(self._config, f, indent=indent, ensure_ascii=False)
    except PermissionError as e:
    raise ConfigError(f\”无法写入配置文件: {

    e}\”) from e

    def reload(self):
    \”\”\”重新加载配置文件\”\”\”
    self._load()

    def to_dict(self)

    赞(0)
    未经允许不得转载:171主机测评 » Python 文件操作与异常处理专项练习:6 道编程题从入门到精通
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址