【问题标题】:celery task decorator throws "TypeError: 'Module object is not callable"芹菜任务装饰器抛出“TypeError:'模块对象不可调用”
【发布时间】:2013-08-08 09:28:12
【问题描述】:

我正在拼命想让 Celery 与 Django 很好地配合,但无济于事。我被以下问题绊倒了:

项目/settings.py:

...

import djcelery
djcelery.setup_loader()

BROKER_URL = 'django://'
CELERY_RESULT_BACKEND = 'django://'
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ENABLE_UTC = True

...

app/tasks.py:

from celery.task import task

@task()
def scheduled_task(param1, param2):
    ...
    return something

直接调用scheduled_task(param1, param2)(没有装饰器)按预期工作。然而,当添加装饰器并像这样启动“开发”芹菜工人时:

python manage.py celery worker --loglevel=info

...我收到以下错误:

TypeError: 'module' object is not callable

我已将其固定在 @task 装饰器上。我尝试的每个组合都失败了,包括:

from celery import task
from celery.task import task
from celery.task.base import task

@task
@task()
@task.task
@task.task()
@celery.task
@celery.task()

似乎对异常中的调用堆栈没有任何影响,他们都似乎认为task 是一个模块,而不是可调用的!让事情变得更令人沮丧:

>>> from celery.task import task
>>> task
<function task at 0x10aa2a758>

这对我来说确实可以调用!知道会发生什么吗?如果我遗漏了什么,我很乐意发布额外的日志、文件或澄清其他任何事情。

【问题讨论】:

  • 可能听起来很明显,但是如果您将所有文件都放在同一个目录中怎么办?另外,你的 manage.py 文件中有什么?
  • 这种令人沮丧的几乎总是是一些被忽视的愚蠢显而易见的事情,没有什么问题是愚蠢的! manage.py 文件目前如下所示:pastebin.com/JaaznH2K
  • 关于目录结构,您是指我的 Django 项目中的文件(它们遵循 Django 1.5 的标准项目模板)还是 django-celerycelery 库/应用程序中的文件?
  • @TrojanCentaur 太棒了,谢谢!由此我认为return backend(app=self, url=url) 是异常发生的地方。所以无论backend 是什么,它似乎都不是可调用的。我会尝试在该文件(celery/app/base.py)中设置一个 pdb 断点,方法是将该行包装在try: ... except: import pdb; pdb.set_trace() 中,然后检查backend,然后向上移动堆栈(pdb 中的u 命令)以调试所有位置出错了。
  • @LukasGraf 3.0.21 在celerydjango-celery 上(通过 pip 安装到 Mac OSX 10.8 上)

标签: python django celery django-celery


【解决方案1】:

以防万一有人使用 Celery beat 并收到相同的错误消息。在我的应用中,我使用了

command=/opt/python/run/venv/bin/celery beat -A appname --loglevel=INFO --workdir=/tmp -S django --pidfile /tmp/celerybeat.pid

并收到此错误消息。由于我使用 supervisord 复制了大部分用于守护 Celery beat 的代码(为此您需要一个特殊的配置),我没有意识到“-S django”假定使用了我之前没有安装的 django_celery_beat 包。我安装了它,因为它无论如何都具有生产使用的优势,并且错误消失了。

【讨论】:

    【解决方案2】:

    (转换为 cmets 的答案)

    stack trace 我认为return backend(app=self, url=url) 行是异常发生的地方。

    所以无论backend 是什么,它似乎都不是可调用的。我会尝试通过将该行包装在该文件(celery/app/base.py)中来设置 pdb 断点

    try:
        backend(app=self, url=url)
    except:
        import pdb; pdb.set_trace(),
    

    然后检查backend,并向上移动堆栈(pdb 中的u 命令,d 再次向下,w 显示调用堆栈)以调试出错的地方。

    celery docs 也提到了这一点:

    如何导入任务装饰器?

    任务装饰器在您的 Celery 实例上可用,如果您不知道它是什么,请阅读 Celery 的第一步。

    如果您正在使用 Django 或仍在使用基于“旧”模块的 celery API,那么您可以像这样导入任务装饰器:

    from celery import task
    
    @task
    def add(x, y):
        return x + y
    

    所以这应该澄清关于导入任务装饰器的方式是正确的方式的任何歧义。

    【讨论】:

    • pdb 看起来很有用,以前没玩过。但是它似乎正在崩溃,我无法判断它是 pdb 崩溃还是故障本身,但是按下c 后我得到的结果如下:pastebin.com/mnYu9vv0
    • 嗯,很有趣。对我来说,目前看起来奇怪的行为可能与您遇到的错误有关:第 3 行base.py(357)_get_backend()-&gt;None 表示_get_backend() 返回None,这几乎解释了您按下c 后的所有后续故障继续:AttributeError: 'NoneType' object has no attribute 'store_result'.
    • 这可能是由于在混合中引入 pdb 引起的 - 在某些框架中,pdb 与普通 Python 中的工作(相同),并且在您检查(并且可能已修改)之后pdb 中的运行时环境,或者在那个断点等待了几分钟,不能保证程序流会像往常一样继续。
    • 但除此之外,我觉得您的问题与结果后端的配置有关。我假设你读过Using the Django ORM/Cache as a result backend? (请注意,这些文档适用于 Celery 的开发版本(当前主版本),而不是最新版本)
    • 我没有使用主版本,只是 3.0.21(通过 pip 分发)。但是在联系 SO 之前,我确实遵循了这些说明,但运气不好!我想知道后端是否指的是CELERY_RESULT_BACKEND,是否迁移到 RabbitMQ 之类的东西可能会有所帮助......
    【解决方案3】:

    这是一个有点老的问题,但我遇到了类似的麻烦,这对我有用:

    项目/settings.py:

    ...
    
    import djcelery
    djcelery.setup_loader()
    
    BROKER_URL = 'django://'
    CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
    CELERY_TASK_SERIALIZER = 'json'
    CELERY_RESULT_SERIALIZER = 'json'
    CELERY_ENABLE_UTC = True
    
    ...
    

    【讨论】:

      猜你喜欢
      • 2020-08-19
      • 1970-01-01
      • 2011-09-17
      • 2021-11-22
      • 2018-05-19
      • 2020-09-22
      • 2017-06-17
      • 2014-09-21
      • 2011-05-30
      相关资源
      最近更新 更多