在Python中,try-except 块用于捕获和处理异常。当 try 块中的代码发生错误时,程序会跳转到对应的 except 块执行。

基本语法结构

try:
    # 可能引发异常的代码
    risky_operation()
except ExceptionType as e:
    # 处理特定类型的异常
    print(f"发生错误: {e}")
except AnotherExceptionType as e:
    # 处理另一种类型的异常
    print(f"另一种错误: {e}")
else:
    # 如果没有发生异常,执行这里的代码
    print("操作成功完成")
finally:
    # 无论是否发生异常,都会执行这里的代码
    print("清理操作")

常见的文件操作异常类型

1. FileNotFoundError

try:
    with open('不存在的文件.txt', 'r', encoding='utf-8') as file:
        content = file.read()
except FileNotFoundError as e:
    print(f"文件不存在错误: {e}")
    print(f"错误文件名: {e.filename}")
    print(f"错误编号: {e.errno}")

2. PermissionError

try:
    with open('/root/受保护的文件.txt', 'w', encoding='utf-8') as file:
        file.write('test')
except PermissionError as e:
    print(f"权限错误: {e}")
    print(f"操作: {e.args[0]}")

3. UnicodeDecodeError

try:
    with open('二进制文件.jpg', 'r', encoding='utf-8') as file:
        content = file.read()
except UnicodeDecodeError as e:
    print(f"编码错误: {e}")
    print(f"错误位置: {e.start}-{e.end}")
    print(f"原因: 尝试用文本模式读取二进制文件")

4. IsADirectoryError

try:
    with open('/某个目录/', 'r', encoding='utf-8') as file:
        content = file.read()
except IsADirectoryError as e:
    print(f"尝试打开目录而不是文件: {e}")

5. IOError (Python 3.3+ 中是 OSError 的别名)

try:
    with open('file.txt', 'r', encoding='utf-8') as file:
        content = file.read()
except IOError as e:
    print(f"输入输出错误: {e}")

错误信息解析方法

获取详细的错误信息

try:
    with open('nonexistent.txt', 'r') as file:
        content = file.read()
except Exception as e:
    print(f"异常类型: {type(e).__name__}")
    print(f"错误信息: {e}")
    print(f"错误参数: {e.args}")
    print(f"完整追溯: {e.__traceback__}")

使用 traceback 模块获取完整堆栈信息

import traceback

try:
    with open('problematic.txt', 'r', encoding='utf-8') as file:
        content = file.read()
except Exception as e:
    print("发生异常:")
    traceback.print_exc()  # 打印完整的堆栈跟踪
    # 或者获取堆栈信息字符串
    error_traceback = traceback.format_exc()
    print("完整的错误信息:")
    print(error_traceback)

实际应用示例

示例1:安全的文件读取函数

def safe_read_file(filename):
    """
    安全读取文件,返回文件内容或错误信息
    """
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            return file.read(), None  # 返回内容和None(表示无错误)
    except FileNotFoundError as e:
        return None, f"错误:文件 '{filename}' 不存在"
    except PermissionError as e:
        return None, f"错误:没有权限读取文件 '{filename}'"
    except UnicodeDecodeError as e:
        return None, f"错误:文件编码问题,请检查文件格式"
    except Exception as e:
        return None, f"未知错误:{e}"

# 使用示例
content, error = safe_read_file('example.txt')
if error:
    print(error)
else:
    print("文件内容:", content)

示例2:带重试机制的文件操作

import time

def read_file_with_retry(filename, max_retries=3, delay=1):
    """
    带重试机制的文件读取
    """
    for attempt in range(max_retries):
        try:
            with open(filename, 'r', encoding='utf-8') as file:
                return file.read()
        except FileNotFoundError as e:
            if attempt == max_retries - 1:  # 最后一次尝试
                raise e
            print(f"文件不存在,{delay}秒后重试... ({attempt + 1}/{max_retries})")
            time.sleep(delay)
        except Exception as e:
            print(f"尝试 {attempt + 1} 失败: {e}")
            if attempt == max_retries - 1:
                raise e
            time.sleep(delay)

示例3:详细的错误日志记录

import logging
import datetime

# 配置日志
logging.basicConfig(
    filename='file_errors.log',
    level=logging.ERROR,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def log_file_operation(operation_func, *args, **kwargs):
    """
    包装文件操作,记录详细的错误日志
    """
    try:
        return operation_func(*args, **kwargs)
    except Exception as e:
        error_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        error_info = {
            'time': error_time,
            'operation': operation_func.__name__,
            'args': args,
            'kwargs': kwargs,
            'error_type': type(e).__name__,
            'error_message': str(e)
        }
        
        logging.error(f"文件操作错误: {error_info}")
        print(f"操作失败,详情已记录到日志。错误: {e}")
        return None

# 使用示例
def read_my_file(filename):
    with open(filename, 'r', encoding='utf-8') as file:
        return file.read()

result = log_file_operation(read_my_file, 'example.txt')

示例4:多异常类型处理

def handle_file_errors(filename, mode='r'):
    try:
        with open(filename, mode, encoding='utf-8') as file:
            if mode == 'r':
                return file.read()
            else:
                return True  # 写入成功
                
    except FileNotFoundError as e:
        print(f"❌ 文件未找到: {filename}")
        print(f"   请检查文件路径是否正确")
        return False
        
    except PermissionError as e:
        print(f"❌ 权限不足: {filename}")
        print(f"   请检查文件权限或是否被其他程序占用")
        return False
        
    except UnicodeDecodeError as e:
        print(f"❌ 编码错误: {filename}")
        print(f"   请尝试使用不同的编码或检查文件格式")
        return False
        
    except IsADirectoryError as e:
        print(f"❌ 尝试打开目录: {filename}")
        print(f"   请提供文件路径而不是目录路径")
        return False
        
    except Exception as e:
        print(f"❌ 未知错误: {type(e).__name__} - {e}")
        return False

最佳实践

  1. 具体异常优先: 先捕获具体的异常类型,最后捕获通用的 Exception
  2. 提供有意义的错误信息: 告诉用户发生了什么以及如何解决
  3. 记录错误日志: 对于生产环境,记录详细的错误信息
  4. 适当的错误恢复: 根据错误类型决定是重试、跳过还是终止
  5. 资源清理: 使用 finally 块或 with 语句确保资源释放

通过这样的错误处理机制,你可以创建更加健壮和用户友好的文件操作程序。