You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为cProfile性能分析装饰器添加方法时遇AttributeError问题排查

问题原因与解决方案

错误原因

你遇到的问题核心在于装饰器的函数替换机制:

  • 装饰器的本质是将原函数替换为内部定义的wrapper函数,最终被赋值给原函数名(比如add)的是wrapper,而非原始的func。
  • 你把print_statistics()方法加到了原始的func对象的属性中,所以打印func.__dict__能看到该方法,但实际调用add.print_statistics()时,Python会去wrapper对象的属性里查找,自然找不到,抛出AttributeError。

简单说:你给A对象加了方法,但实际调用的是B对象,当然找不到。

解决方法

把print_statistics()方法直接加到wrapper函数对象上,同时将性能统计的cProfile.Profile实例与wrapper绑定,确保统计数据能被正确访问。

示例代码如下:

import cProfile
import functools

def profile_decorator(func):
    # 初始化性能分析器,与wrapper绑定
    pr = cProfile.Profile()

    @functools.wraps(func)  # 可选,保留原函数的名称、文档等元信息
    def wrapper(*args, **kwargs):
        pr.enable()
        try:
            # 执行原函数
            return func(*args, **kwargs)
        finally:
            pr.disable()

    # 定义统计打印方法,并绑定到wrapper上
    def print_statistics():
        # 输出性能统计表格,可指定排序规则(比如按累计耗时排序)
        pr.print_stats(sort='cumulative')

    wrapper.print_statistics = print_statistics
    return wrapper

# 使用装饰器
@profile_decorator
def add(a, b):
    return a + b

# 调用被装饰的函数
add(1, 2)
add(3, 4)

# 调用统计方法
add.print_statistics()

关键说明

  • pr实例定义在装饰器外层,与wrapper形成闭包,确保每次调用wrapper时都能复用同一个分析器,累计统计数据。
  • print_statistics方法直接赋值给wrapper,这样add(即wrapper)就拥有了该方法,调用时不会出错。
  • 使用functools.wraps是为了让wrapper保留原函数的元信息(比如函数名、文档字符串),避免混淆,但不是必须的。

内容的提问来源于stack exchange,提问作者zaelcovsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:06:07