使用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
相关产品推荐
相关产品推荐

