如何在Celery的task_prerun中获取任务签名与参数名值对?
问题
需要记录所有Celery任务请求及其接收的参数,当前使用以下代码实现日志功能:
@task_prerun.connect() def log_celery_args(task, **kwargs): logger.info(f"{task.name} {kwargs['kwargs']}", extra=kwargs['kwargs'])
但该方案在任务函数使用非命名参数时失效:虽然能从kwargs['args']获取参数值,但无法在日志extra中保持{参数名: 值}的格式。
已尝试的操作:
- 打印
task和task.request的所有参数查找相关信息; - 发现
signature函数但仅用于修改签名; - 尝试使用
celery.app.trace模块实现带参数名的日志记录。
解决方案
可以通过Python的inspect模块获取任务函数的参数签名,将位置参数(args)和关键字参数(kwargs)合并成带参数名的字典,具体实现如下:
import inspect from celery.signals import task_prerun @task_prerun.connect() def log_celery_args(task, **kwargs): # 获取任务函数的参数签名 sig = inspect.signature(task.run) # 绑定位置参数和关键字参数到签名 bound_args = sig.bind(*kwargs['args'], **kwargs['kwargs']) bound_args.apply_defaults() # 填充默认参数 # 得到包含所有参数名和值的字典 full_args = bound_args.arguments # 记录日志,extra使用带参数名的字典 logger.info(f"{task.name} {full_args}", extra=full_args)
说明
task.run是Celery任务实际执行的函数,通过inspect.signature获取它的参数定义;sig.bind()会把位置参数按顺序映射到对应的参数名,自动处理位置参数和关键字参数的合并;apply_defaults()会自动填充函数定义中的默认参数值,确保日志记录完整;- 最终
full_args就是{参数名: 参数值}格式的字典,完美适配日志extra的需求。
内容的提问来源于stack exchange,提问作者Dany Y
相关产品推荐
相关产品推荐

