Python编译、导入与运行时错误全指南

0 阅读14分钟

一、Python代码执行流程详解

1. Python代码执行阶段

源代码 (.py)
    ↓
词法分析 → 词法错误
    ↓
语法分析 → 语法错误
    ↓
字节码编译 → 编译时错误
    ↓
字节码文件 (.pyc/.pyo)
    ↓
导入/执行 → 导入错误
    ↓
字节码解释执行 → 运行时错误
    ↓
JIT编译(PyPy等)→ 优化错误

2. Python与编译型语言的关键区别

特性PythonC/C++/Java
编译时机运行时编译预先编译
错误检测运行时为主编译时为主
类型检查运行时(动态)编译时(静态)
链接过程导入时动态链接编译/链接时静态链接

二、Python编译阶段错误

1. 词法分析错误(Lexical Errors)

非法字符错误

# 错误示例1:非法Unicode字符
# 保存为UTF-8但包含非法BOM
# 文件开头有不可见字符

# 错误示例2:全角符号
print"Hello"# 使用中文括号

# 错误示例3:非法转义字符
path = "C:\new\file.txt"  # \n被解释为换行符

检测与解决

# 1. 使用chardet检测编码
import chardet

with open('problematic.py', 'rb') as f:
    raw_data = f.read()
    result = chardet.detect(raw_data)
    print(f"检测到编码: {result['encoding']}")

# 2. 使用-tt参数检查tab/空格混合
# python -tt script.py
# 输出:TabError: inconsistent use of tabs and spaces in indentation

# 3. 使用编辑器显示隐藏字符
# VS Code: 查看 -> 显示 -> 显示所有字符
# Notepad++: 视图 -> 显示符号 -> 显示所有字符

# 4. 统一使用UTF-8编码
# 在文件开头添加编码声明
# -*- coding: utf-8 -*-

# 5. 正确处理转义字符
path = r"C:\new\file.txt"  # 原始字符串
# 或
path = "C:\new\file.txt"  # 双反斜杠

2. 语法错误(Syntax Errors)

基本语法错误

# 错误示例1:缩进错误
def func():
print("Hello")  # 缺少缩进
    print("World")  # 不一致的缩进

# 错误示例2:括号不匹配
result = (1 + 2 * (3 + 4)  # 缺少右括号

# 错误示例3:冒号缺失
if x > 0
    print("Positive")

# 错误示例4:无效语法
x = 10
y = 20
x = y =  # 赋值语句不完整

解决方案

# 1. 使用IDE/编辑器的语法检查
# Pylint, flake8, black等工具

# 2. Python语法检查命令
python -m py_compile script.py
# 或
python -m py_compile -o output.pyc script.py

# 3. 使用ast模块检查语法
import ast

def check_syntax(filename):
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            source = f.read()
        ast.parse(source)
        print(f"{filename}: 语法正确")
    except SyntaxError as e:
        print(f"{filename}: 语法错误")
        print(f"  行 {e.lineno}: {e.msg}")
        print(f"  内容: {e.text}")

# 4. 统一缩进风格
# 使用4个空格,不要混用Tab和空格
# 配置编辑器:设置 -> 转换为空格,缩进=4

# 5. 括号自动补全工具
# 使用VS Code、PyCharm等支持括号匹配的编辑器

Python版本特定的语法错误

# Python 3.7+ 的async/await语法
# 错误:在非async函数中使用await
def sync_func():
    result = await async_call()  # SyntaxError

# Python 3.8+ 的海象运算符
# 错误:在Python 3.7中使用
if (x := 10) > 5:  # Python 3.8+ 语法
    pass

# 类型注解语法
# Python 3.5+: 类型提示
def func(x: int) -> int:  # Python 3.5+
    return x * 2

# 但在Python 2.7中会报错

版本兼容性检查

# 1. 使用__future__导入
from __future__ import annotations  # Python 3.7+的类型注解延迟求值
from __future__ import print_function  # Python 2中启用print函数

# 2. 检查Python版本
import sys

if sys.version_info < (3, 7):
    raise RuntimeError("需要Python 3.7或更高版本")

# 3. 使用six等兼容性库
import six

# 4. tox多版本测试
# tox.ini配置
[tox]
envlist = py27, py35, py36, py37, py38, py39

[testenv]
deps = pytest
commands = pytest

3. 字节码编译错误

compile()函数错误

# 动态编译错误
source_code = """
def broken_func():
    return 1 +  # 语法错误
"""

try:
    code_obj = compile(source_code, '<string>', 'exec')
    exec(code_obj)
except SyntaxError as e:
    print(f"编译错误: {e}")

动态编译的调试

import dis
import traceback

def safe_compile(source, filename, mode):
    """安全的编译函数"""
    try:
        # 先尝试语法分析
        tree = ast.parse(source, filename)
        
        # 再编译
        code_obj = compile(source, filename, mode)
        
        # 可以反汇编查看字节码
        if __debug__:
            print(f"反汇编 {filename}:")
            dis.dis(code_obj)
        
        return code_obj
    except SyntaxError as e:
        # 增强错误信息
        print(f"语法错误在 {filename}:{e.lineno}")
        if e.text:
            print(f"  行内容: {e.text.rstrip()}")
            print(f"  {' ' * (e.offset-1)}^")
        print(f"  错误: {e.msg}")
        raise
    except ValueError as e:
        print(f"编译错误: {e}")
        raise

# 使用示例
code = """
def calculate(x, y):
    return x + y
"""

try:
    compiled = safe_compile(code, "test.py", "exec")
    exec(compiled)
    result = calculate(10, 20)
    print(f"结果: {result}")
except Exception as e:
    traceback.print_exc()

三、导入(链接)错误

1. 模块导入错误(ImportError)

基本导入错误

# 错误示例1:模块不存在
import non_existent_module  # ImportError: No module named 'non_existent_module'

# 错误示例2:从模块导入不存在的成员
from os import non_existent_function  # ImportError: cannot import name 'non_existent_function'

# 错误示例3:循环导入
# module_a.py
import module_b
# module_b.py  
import module_a  # 可能导致循环导入

# 错误示例4:相对导入错误
# package/sub.py
from ..sibling import func  # 在顶层脚本中使用会报错

解决方案

# 1. 检查模块搜索路径
import sys
print("Python路径:")
for path in sys.path:
    print(f"  {path}")

# 2. 动态添加路径
import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

# 3. 使用try-except处理导入
try:
    import optional_module
except ImportError:
    optional_module = None
    print("警告: optional_module未安装")

# 4. 条件导入
if some_condition:
    import module_a as module
else:
    import module_b as module

# 5. 延迟导入(在函数内部导入)
def lazy_import():
    import expensive_module
    return expensive_module.some_function()

# 6. 使用importlib动态导入
import importlib

def import_module_safely(module_name):
    try:
        module = importlib.import_module(module_name)
        return module
    except ImportError as e:
        print(f"无法导入 {module_name}: {e}")
        return None

# 7. 检查包结构
# 确保有__init__.py文件(Python 3.3+可选,但建议有)
# 正确的包结构:
# my_package/
#   __init__.py
#   module1.py
#   subpackage/
#     __init__.py
#     module2.py

包导入的特殊问题

# 错误:相对导入在顶层模块中使用
# script.py
from .mymodule import func  # 错误: attempted relative import with no known parent package

# 错误:__init__.py问题
# 如果__init__.py中有语法错误,导入整个包都会失败

包导入调试

# 1. 使用__package__检查
print(f"当前包: {__package__}")

# 2. 使用绝对导入避免相对导入问题
# 在setup.py中正确配置
from setuptools import setup, find_packages

setup(
    name='mypackage',
    packages=find_packages(),
    # ...
)

# 3. 使用pkgutil的扩展路径
import pkgutil
import pkg_resources

# 发现所有插件
discovered_plugins = {
    name: importlib.import_module(name)
    for finder, name, ispkg in pkgutil.iter_modules()
    if name.startswith('mypackage_')
}

# 4. 命名空间包(Python 3.3+)
# 多个目录可以共同组成一个包
# 不需要__init__.py文件
# 在setup.py中声明namespace_packages

2. 导入时执行错误

模块初始化错误

# module_with_error.py
# 模块级别的代码执行错误
x = 1 / 0  # ZeroDivisionError

# 另一个文件
import module_with_error  # 导入时立即出错

安全导入模式

# 1. 使用importlib的懒加载模式
import importlib.util
import sys

def load_module_safely(module_name, module_path):
    """安全加载模块,捕获初始化错误"""
    spec = importlib.util.spec_from_file_location(module_name, module_path)
    if spec is None:
        print(f"无法创建模块规范: {module_name}")
        return None
    
    module = importlib.util.module_from_spec(spec)
    
    try:
        spec.loader.exec_module(module)
        return module
    except Exception as e:
        print(f"导入模块 {module_name} 时出错: {e}")
        return None

# 2. 将模块级代码移到函数中
# bad_module.py
CONFIG = load_config()  # 可能失败
DB = connect_database()  # 可能失败

# good_module.py
_config = None
_db = None

def get_config():
    global _config
    if _config is None:
        _config = load_config()
    return _config

def get_db():
    global _db
    if _db is None:
        _db = connect_database()
    return _db

# 3. 使用try-except包装模块级代码
# safe_module.py
try:
    from .config import settings
except ImportError:
    settings = {}

try:
    import optional_dependency
except ImportError:
    optional_dependency = None

3. 动态导入和插件系统错误

# 动态导入插件
import importlib
import pkgutil
import os

class PluginManager:
    def __init__(self, plugin_dir):
        self.plugin_dir = plugin_dir
        self.plugins = {}
        self.errors = []
    
    def load_plugins(self):
        """加载所有插件"""
        for filename in os.listdir(self.plugin_dir):
            if filename.endswith('.py') and not filename.startswith('_'):
                module_name = filename[:-3]
                self.load_plugin(module_name)
    
    def load_plugin(self, module_name):
        """加载单个插件"""
        try:
            # 动态导入
            module = importlib.import_module(f'.{module_name}', package='plugins')
            
            # 检查插件接口
            if hasattr(module, 'Plugin'):
                plugin_class = module.Plugin
                plugin_instance = plugin_class()
                
                # 注册插件
                self.plugins[module_name] = plugin_instance
                print(f"成功加载插件: {module_name}")
            else:
                self.errors.append(f"插件 {module_name} 缺少Plugin类")
                
        except ImportError as e:
            self.errors.append(f"导入插件 {module_name} 失败: {e}")
        except Exception as e:
            self.errors.append(f"初始化插件 {module_name} 失败: {e}")
    
    def report_errors(self):
        """报告所有错误"""
        if self.errors:
            print("插件加载错误:")
            for error in self.errors:
                print(f"  - {error}")

四、字节码和优化相关错误

1. 字节码操作错误

marshal/unmarshal错误

# 错误:尝试marshal不支持的类型
import marshal

data = {
    'func': lambda x: x*2,  # lambda函数不能被marshal
    'generator': (x for x in range(10))  # 生成器也不能
}

try:
    marshaled = marshal.dumps(data)  # ValueError
except Exception as e:
    print(f"marshal失败: {e}")

安全序列化

# 1. 使用pickle替代marshal
import pickle
import dill  # 可以序列化更多类型

# 2. 检查可序列化性
def is_marshalable(obj):
    """检查对象是否可以被marshal"""
    try:
        marshal.dumps(obj)
        return True
    except ValueError:
        return False

# 3. 自定义序列化
import json
from datetime import datetime

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        elif hasattr(obj, '__dict__'):
            return obj.__dict__
        return super().default(obj)

# 4. 使用__reduce__控制pickle行为
class Serializable:
    def __init__(self, data):
        self.data = data
    
    def __reduce__(self):
        return (self.__class__, (self.data,))

2. 编译优化错误

常量折叠和优化问题

# Python的常量折叠可能导致的微妙错误
def create_functions():
    """创建一系列函数,但它们都使用相同的i"""
    functions = []
    for i in range(3):
        def func():
            return i
        functions.append(func)
    return functions

funcs = create_functions()
print([f() for f in funcs])  # 输出[2, 2, 2],不是[0, 1, 2]

# 修复:使用默认参数捕获当前值
def create_functions_fixed():
    functions = []
    for i in range(3):
        def func(x=i):  # 默认参数在定义时求值
            return x
        functions.append(func)
    return functions

Python优化模式

# 使用-O或-OO优化标志
python -O script.py  # 移除assert语句和__debug__代码
python -OO script.py  # 同时移除文档字符串

# 优化可能引发的问题
def debug_function():
    """只在调试模式下执行的代码"""
    if __debug__:
        print("调试信息")
        # 重要但非关键的初始化
        init_debug_system()
    
    # 主逻辑
    return compute()

# 使用-O运行时,init_debug_system()不会执行

五、扩展模块错误(C扩展)

1. C扩展编译错误

# setup.py
from setuptools import setup, Extension

module = Extension(
    'mymodule',
    sources=['mymodule.c'],
    include_dirs=['/usr/local/include'],
    library_dirs=['/usr/local/lib'],
    libraries=['mylib']
)

setup(
    name='MyPackage',
    ext_modules=[module]
)

编译错误诊断

# 1. 使用distutils获取详细输出
python setup.py build_ext --inplace --verbose

# 2. 检查编译器标志
import sys
import sysconfig
print(f"编译器: {sysconfig.get_config_var('CC')}")
print(f"编译标志: {sysconfig.get_config_var('CFLAGS')}")
print(f"链接标志: {sysconfig.get_config_var('LDFLAGS')}")

# 3. 使用cibuildwheel跨平台编译
# .github/workflows/build.yml
# 配置多平台CI构建

# 4. 检查Python头文件路径
import sys
import os
include_dir = sysconfig.get_path('include')
print(f"Python头文件目录: {include_dir}")

# 5. 使用pybind11简化C++扩展
#include <pybind11/pybind11.h>
PYBIND11_MODULE(mymodule, m) {
    m.def("add", [](int a, int b) { return a + b; });
}

2. C扩展导入错误

# 错误:ABI不兼容
# 在Python 3.8编译的扩展,在Python 3.9导入
# ImportError: dynamic module does not define module export function

# 错误:缺少依赖库
# ImportError: libmylib.so: cannot open shared object file: No such file or directory

解决方案

# 1. 检查扩展模块兼容性
import importlib.util
import sys

def check_extension_compatibility(module_path):
    """检查扩展模块兼容性"""
    spec = importlib.util.spec_from_file_location("test", module_path)
    
    # 检查文件魔数
    with open(module_path, 'rb') as f:
        magic = f.read(4)
        # Python 3.x的魔数是不同的
    
    # 尝试加载
    try:
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        return True
    except ImportError as e:
        print(f"导入失败: {e}")
        return False

# 2. 使用wheel的ABI标签
# 正确的wheel命名: package-version-cp39-cp39-manylinux_2_31_x86_64.whl
# cp39表示Python 3.9,abi3表示兼容所有Python 3.x

# 3. 在setup.py中声明兼容性
from setuptools import setup, Extension
import sys

# 使用Py_LIMITED_API支持ABI3
if sys.version_info >= (3, 2):
    define_macros = [('Py_LIMITED_API', '0x03020000')]
else:
    define_macros = []

module = Extension(
    'mymodule',
    sources=['mymodule.c'],
    define_macros=define_macros,
    py_limited_api=True
)

六、调试和诊断工具

1. Python调试工具集

# 1. 使用pdb调试器
import pdb

def problematic_function(x):
    result = 0
    for i in range(x):
        pdb.set_trace()  # 设置断点
        result += i * 2
    return result

# 2. 使用icecream增强调试
# pip install icecream
from icecream import ic

def debug_with_ic():
    x = 10
    y = 20
    ic(x, y, x + y)  # 自动打印变量名和值
    return x + y

# 3. 使用faulthandler处理段错误
import faulthandler
import signal

faulthandler.enable()  # 启用
faulthandler.register(signal.SIGUSR1)  # 注册信号

# 4. 使用traceback获取详细错误
import traceback
import sys

def safe_call(func, *args):
    try:
        return func(*args)
    except Exception:
        # 获取完整的堆栈跟踪
        exc_type, exc_value, exc_tb = sys.exc_info()
        tb_lines = traceback.format_exception(exc_type, exc_value, exc_tb)
        print("".join(tb_lines))
        raise

# 5. 使用cProfile性能分析
import cProfile
import pstats
from io import StringIO

def profile_function(func, *args):
    pr = cProfile.Profile()
    pr.enable()
    
    result = func(*args)
    
    pr.disable()
    s = StringIO()
    ps = pstats.Stats(pr, stream=s).sort_stats('cumulative')
    ps.print_stats(20)  # 显示前20行
    print(s.getvalue())
    
    return result

2. 静态分析工具

# 1. pyflakes - 检查语法错误和未使用变量
pip install pyflakes
pyflakes script.py

# 2. pylint - 代码质量检查
pip install pylint
pylint script.py

# 3. mypy - 静态类型检查
pip install mypy
mypy --strict script.py

# 4. bandit - 安全漏洞检查
pip install bandit
bandit -r myproject/

# 5. black - 代码格式化
pip install black
black script.py

# 6. isort - 导入排序
pip install isort
isort script.py

# 7. flake8 - 综合检查
pip install flake8
flake8 script.py

3. 动态分析工具

# 1. 使用sys.settrace跟踪执行
import sys

def trace_calls(frame, event, arg):
    if event == 'call':
        print(f"调用: {frame.f_code.co_name}{frame.f_code.co_filename}:{frame.f_lineno}")
    return trace_calls

sys.settrace(trace_calls)

# 2. 使用inspect检查运行时代码
import inspect

def get_current_stack():
    """获取当前调用堆栈"""
    stack = inspect.stack()
    for frame_info in stack[1:]:  # 跳过当前函数
        print(f"{frame_info.filename}:{frame_info.lineno} in {frame_info.function}")
        print(f"  代码: {frame_info.code_context}")

# 3. 使用objgraph调试内存
# pip install objgraph
import objgraph

def find_memory_leaks():
    """查找内存泄漏"""
    # 显示最常见类型
    objgraph.show_most_common_types(limit=20)
    
    # 显示增长
    objgraph.show_growth(limit=10)

七、常见错误模式及解决方案

1. 错误模式速查表

错误类型示例可能原因解决方案
SyntaxErrorinvalid syntax语法错误检查拼写、缩进、括号
IndentationErrorunexpected indent缩进错误统一使用4个空格
TabErrorinconsistent tabs/spaces制表符/空格混用转换制表符为空格
ImportErrorNo module named 'x'模块不存在安装模块,检查PYTHONPATH
ModuleNotFoundError同ImportErrorPython 3.6+的新名称同上
AttributeError'module' has no attribute 'x'属性不存在检查拼写,查看模块文档
TypeErrorunsupported operand type(s)类型不匹配检查类型,使用类型转换
ValueErrorinvalid literal for int()值格式错误验证输入数据
NameErrorname 'x' is not defined变量未定义检查作用域,导入模块
KeyErrorkey not found字典键不存在使用dict.get()或检查键
IndexErrorlist index out of range索引越界检查列表长度
ZeroDivisionErrordivision by zero除以零添加除数检查
FileNotFoundError[Errno 2] No such file文件不存在检查路径,创建文件
PermissionError[Errno 13] Permission denied权限不足修改权限,以管理员运行

2. Python 2/3兼容性错误

# Python 2/3兼容性常见问题
from __future__ import print_function, division, absolute_import, unicode_literals

# 1. print语句/函数
print "Hello"  # Python 2
print("Hello")  # Python 3

# 2. 整数除法
result = 3 / 2  # Python 2: 1, Python 3: 1.5
result = 3 // 2  # 两者都是1

# 3. Unicode字符串
text = "Hello"  # Python 2: bytes, Python 3: str
text = u"Hello"  # Python 2: unicode, Python 3: str

# 4. xrange/range
for i in xrange(10):  # Python 2
for i in range(10):   # Python 3

# 5. 字典迭代
d = {'a': 1, 'b': 2}
keys = d.keys()  # Python 2: 列表, Python 3: 视图
values = d.values()  # 同上
items = d.items()  # 同上

# 兼容性解决方案
import six

if six.PY2:
    # Python 2代码
    text = unicode("Hello")
    range_func = xrange
else:
    # Python 3代码
    text = str("Hello")
    range_func = range

八、最佳实践和预防措施

1. 防御性编程

# 1. 类型注解和检查
from typing import Optional, List, Dict, Any
import typing

def process_data(data: List[Dict[str, Any]]) -> Optional[float]:
    """处理数据,返回结果或None"""
    if not data:
        return None
    
    # 运行时类型检查
    if not isinstance(data, list):
        raise TypeError(f"期望list,得到{type(data).__name__}")
    
    # 使用mypy进行静态检查
    # mypy --strict script.py
    
    return 42.0

# 2. 输入验证装饰器
from functools import wraps

def validate_input(validation_func):
    """输入验证装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if not validation_func(*args, **kwargs):
                raise ValueError("输入验证失败")
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 3. 使用assert进行内部检查
def critical_function(data):
    """关键函数,使用assert验证不变式"""
    assert data is not None, "data不能为None"
    assert len(data) > 0, "data不能为空"
    
    # 主逻辑
    result = sum(data) / len(data)
    
    # 后置条件检查
    assert isinstance(result, (int, float)), "结果必须是数字"
    return result

# 4. 使用try-except处理预期错误
def robust_file_read(filename):
    """健壮的文件读取"""
    try:
        with open(filename, 'r', encoding='utf-8') as f:
            return f.read()
    except FileNotFoundError:
        print(f"警告: 文件 {filename} 不存在")
        return ""
    except UnicodeDecodeError:
        print(f"警告: 文件 {filename} 编码错误")
        try:
            with open(filename, 'r', encoding='latin-1') as f:
                return f.read()
        except Exception:
            return ""
    except Exception as e:
        print(f"读取文件 {filename} 时出错: {e}")
        return ""

# 5. 使用上下文管理器管理资源
from contextlib import contextmanager
import tempfile
import os

@contextmanager
def temporary_file(suffix=".txt"):
    """临时文件上下文管理器"""
    fd, path = tempfile.mkstemp(suffix=suffix)
    try:
        os.close(fd)
        yield path
    finally:
        try:
            os.unlink(path)
        except OSError:
            pass

2. 项目配置和工具

# setup.py - 项目配置
from setuptools import setup, find_packages

setup(
    name="myproject",
    version="1.0.0",
    packages=find_packages(),
    install_requires=[
        "requests>=2.25.0",
        "numpy>=1.19.0",
    ],
    extras_require={
        "dev": [
            "pytest>=6.0",
            "pytest-cov>=2.0",
            "black>=20.0",
            "mypy>=0.800",
        ],
        "docs": [
            "sphinx>=3.0",
            "sphinx-rtd-theme>=0.5",
        ],
    },
    python_requires=">=3.7",
    entry_points={
        "console_scripts": [
            "myproject=myproject.cli:main",
        ],
    },
)

# pyproject.toml - 现代配置
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[tool.black]
line-length = 88
target-version = ['py37', 'py38', 'py39']

[tool.isort]
profile = "black"
multi_line_output = 3

[tool.mypy]
python_version = 3.7
warn_return_any = true
warn_unused_configs = true

3. 错误处理和日志

# logging_config.py
import logging
import logging.config
import json
import sys

# 配置日志
LOGGING_CONFIG = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "detailed": {
            "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        },
        "simple": {
            "format": "%(levelname)s: %(message)s"
        }
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "level": "INFO",
            "formatter": "simple",
            "stream": sys.stdout
        },
        "file": {
            "class": "logging.handlers.RotatingFileHandler",
            "level": "DEBUG",
            "formatter": "detailed",
            "filename": "app.log",
            "maxBytes": 10485760,  # 10MB
            "backupCount": 5
        }
    },
    "loggers": {
        "myapp": {
            "level": "DEBUG",
            "handlers": ["console", "file"],
            "propagate": False
        }
    },
    "root": {
        "level": "WARNING",
        "handlers": ["console"]
    }
}

# 初始化日志
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("myapp")

# 错误处理装饰器
def log_exceptions(func):
    """记录异常并重新抛出"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            logger.exception(f"函数 {func.__name__} 执行失败: {e}")
            raise
    return wrapper

# 使用示例
@log_exceptions
def risky_operation():
    """可能失败的操作"""
    result = 1 / 0
    return result

记住:Python的错误处理哲学是"请求宽恕比请求许可更容易"。通过恰当的异常处理、日志记录和防御性编程,可以构建出健壮可靠的Python应用。