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

使用inspect获取Celery装饰任务函数名返回__protected_call__如何处理

Celery装饰任务获取真实函数名解决方案

问题原因

Celery对异步任务函数做装饰时,会在原始函数外层套多层内部wrapper逻辑,__protected_call__就是Celery内部调用任务时的包装函数,你通过inspect.stack()[1].function直接取到的上层栈帧属于Celery内部逻辑,自然拿不到原始函数名。

可用解决方案

方案1:直接读取Celery任务实例的name属性

如果是在任务内部获取自身的真实名称,直接读取任务实例的内置name属性即可,默认值为「模块名.原始函数名」,也可以在装饰器中自定义:

from celery import Celery

app = Celery('tasks', broker='pyamqp://guest@localhost//')

# 自定义name参数,不填则默认用模块+函数名
@app.task(name='user_define_task_name')
def your_async_func():
    # 直接读取任务实例的name属性
    real_name = your_async_func.name

# 如果用bind参数绑定任务实例到self参数,写法如下
@app.task(bind=True, name='user_define_task_name')
def your_async_func(self):
    real_name = self.name

方案2:栈回溯跳过Celery内部层

如果必须通过inspect模块的栈回溯能力获取,就遍历所有栈帧,跳过Celery内部的函数层,匹配到业务代码的函数即可:

import inspect

def get_real_caller_name():
    for frame in inspect.stack():
        # 跳过Celery内部文件和魔法方法
        if "celery" in frame.filename.lower() or frame.function.startswith("__"):
            continue
        return frame.function
    return None

方案3:通过__wrapped__属性取原始函数

Celery的任务装饰器默认已用functools.wraps保留原始函数元信息,你可以直接从任务实例的__wrapped__属性拿到原始函数,读取它的__name__:

# your_async_func是被Celery装饰后的任务实例
real_func_name = your_async_func.__wrapped__.__name__

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:54:04