【问题标题】:Python custom decorator not working with Celery tasks [duplicate]Python自定义装饰器不适用于芹菜任务[重复]
【发布时间】:2018-05-19 16:20:35
【问题描述】:

我在使用 Python 装饰器时遇到了一些麻烦。我有一个这样设置的场景:

def decorated(func):
    def call_and_update(*args, **kwargs):
        # do some stuff here
        output = func(*args, **kwargs)
        # do more stuff here
        return output
    return call_and_update

@celery.task
@decorated
def testA():
    return "Test A"

@celery.task
@decorated
def testB():
    return "Test B"

由于某种原因,我首先调用的函数似乎在装饰器中被保留为func

例如,如果我启动一个 shell 并运行:

>>> testA()
Test A
>>> testB()
Test A

或者,如果我重新启动 shell 并开始第二个测试:

>>> testB()
Test B
>>>> testA()
Test B

我找到了this question with a similar issue,但少数答案围绕着使用扩展类来代替任务方法。

如果我特别想通过装饰器和函数来做到这一点,有什么技巧可以让它发挥作用吗?

请注意,没有 @celery.task 装饰器,功能正常工作。正是这两个装饰器的组合导致了问题。

谢谢!

【问题讨论】:

  • 您是否仅在使用 celery-task 装饰器时看到此行为?
  • @juanpa.arrivillaga 正确。没有 celery.task 装饰器,这些功能正常工作。 (我会在问题中记下这一点)
  • 这是重复的。 TLDR:使用functools.wraps(),这样celery 任务就可以记录正确的函数名(否则你所有的任务都被命名为call_and_update)。
  • @MartijnPieters 太棒了,谢谢!这也很有效,让事情变得更容易。

标签: python celery decorator python-decorators


【解决方案1】:

每个任务都需要有一个唯一的名称celery docs,因为没有提供它使用您的包装函数的名称。

@celery.task(name='test-A')
@decorated
def testA():
    return 'test A'

@celery.task(name='test-B')
@decorated
def testB():
    return 'test B'

【讨论】:

  • 是的,做到了!忘了这一点 - 似乎它自然默认为函数名称,但是当函数被额外的 @decorated 装饰器包围时,它们都默认使用该装饰器函数名称。谢谢!
  • @CaptainPlanet:您也可以在 decorated 函数中使用 functools.wraps。这将通过更新其名称使您的装饰函数“看起来”像原始函数。
猜你喜欢
  • 2011-09-17
  • 2013-10-30
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2015-01-20
  • 2015-08-12
相关资源
最近更新 更多