【问题标题】:ImportError: cannot import name celeryImportError:无法导入名称芹菜
【发布时间】:2016-11-06 06:52:41
【问题描述】:

我正在尝试使用 Celery + Redis + Flask 运行一些后台作业。

我的应用结构是:

myapp/
  celery_worker.py
  manage.py
  myapp/
    __init__.py
    app.py
    bot/
      __init__.py
      tasks.py
    accounts/
      views.py

我将 celery 初始化为 app.py 为:

celery = Celery('tasks', include=['bot.tasks'])

def create_app(config=None, app_name=None, blueprints=None):
    # more Celery and other config here like celery.conf.update()

然后通过celery_worker.py启动worker

from myapp import create_app, celery

app = create_app()
app.app_context().push()

tasks.py 包含

from myapp import celery

@celery.task(name='my_task_bot')
def my_task_bot():
     # pass

现在,当我尝试通过以下导入将任务从 tasks.py 访问到 accounts/views.py 时:

from ..bot.tasks import my_task_bot

我收到ImportError: cannot import name celery 错误。

无论我在哪里尝试导入任务,我都会收到此错误。这个celery 实例似乎是在 app.py 中初始化的实例,但没有被导入。

PS:我遵循https://github.com/ezequielo/flask_celery_exp repo 的模式,它工作正常。但不是我的应用。

编辑:

这是回溯:

Traceback (most recent call last):
  File "manage.py", line 8, in <module>
    from myapp import create_app
  File "/home/mars/myapp/myapp/__init__.py", line 3, in <module>
    from app import create_app, celery
  File "/home/mars/myapp/myapp/app.py", line 18, in <module>
    from .accounts import (accounts, AccountsAdmin) 
  File "/home/mars/myapp/myapp/accounts/__init__.py", line 7, in <module>
    from .views import accounts
  File "/home/mars/myapp/myapp/accounts/views.py", line 6, in <module>
    from ..bot.tasks import my_task_bot
  File "/home/mars/myapp/myapp/bot/tasks.py", line 14, in <module>
    from myapp import celery
ImportError: cannot import name celery

Fatal error: local() encountered an error (return code 1) while executing 'python manage.py initdb'

我在尝试启动 manage.pycelery_worker 时遇到上述错误。

请提出建议。

【问题讨论】:

    标签: python flask celery


    【解决方案1】:

    您的导入逻辑不正确,导致循环依赖。不要在 app.py 中连同引用模块 (accounts) 一起初始化 celery,该模块反过来导入 celery 实例。

    您有多种选择:

    1. 从 app.py 模块中的应用 accounts 移除依赖

    2. 将 celery 初始化对象放入不引用任何其他模块,而是由/*/tasks.py 子模块引用的共享模块中。

    3. 不要在任务中导入 celery,而是使用 shared_task 装饰器。更多信息请参考doc

    重要提示:不要忘记将 celery 应用正确链接到您的 @shared_tasks。 Celery 应用程序应该在任何任务之前加载。因此,在 celery.py 中定义 celery 初始化,然后在 myapp/__init__.py 加载它。

    from __future__ import absolute_import
    
    from .celery import app as celery_app  # noqa
    

    或者,您可以对此link 进行详细说明。它展示了一种将烧瓶应用程序与 celery 应用程序一起组织的好方法。

    【讨论】:

    • 现在,我在尝试从烧瓶应用程序运行任务时收到 socket.error: [Errno 111] Connection refused 错误。它与@shared_task 有关吗?正如在文档中提到的,这个装饰器在没有任何具体实例的情况下创建任务
    • No celery doc 的意思是“@shared_task 装饰器允许您创建任何应用程序都可以使用的任务。”。我在金字塔、烧瓶、django 中以下列方式使用它。你能提供更多细节吗?您使用哪个经纪人?如果是redis,你确定它正在运行吗?如果您提供配置详细信息会更好。
    • gist.github.com/anonymous/fcfd7b4fe6af8661822c38773b0612a2 周期性任务正常运行,'celery status' 命令给出 +ve 结果。唯一的问题是当我尝试根据用户输入调用/运行命令时(在烧瓶应用程序中,例如单击表单/按钮),然后我收到 Connection refused 错误。
    • 我明白了。这意味着您的任务在 celery 应用程序之前加载,然后 shared_task 和您的 celery 应用程序之间没有正确的链接。您可以尝试将 celery 导入 myapp.__init__ 模块。但为此,您需要通过循环导入来解决错误。然后我确信你的芹菜是在实际任务之前加载并链接正确的设置。希望对你有帮助
    • 在回答中添加了重要部分
    【解决方案2】:

    在初始化 Celery 的文件中,将其添加为第一行。

    from __future__ import absolute_import
    

    解释

    from __future__ import absolute_import 表示如果你导入 celery,Python 会寻找一个顶级的 celery 模块,而不是 current_package.celery。这应该可以解决您遇到的错误。但要确保芹菜是 安装。值得一提的是必须安装 celery。这适用于 python 2.6以后的版本

    【讨论】:

      【解决方案3】:

      tasks.py

      from myapp.app import celery
      

      https://docs.python.org/3.5/tutorial/modules.html#packages

      【讨论】:

      • 已经在上面尝试过,但仍然得到相同的ImportError。我已经更新了原始问题的引用。看那个。
      • 对,看我的回答
      • 我明白了。这意味着您的任务在 celery 应用程序之前加载,然后 shared_task 和您的 celery 应用程序之间没有正确的链接。您可以尝试在myapp.__init__ 模块中导入芹菜:
      【解决方案4】:

      我解决了这个错误,在 pycharm 中取消选中“将内容根添加到 python 路径”和“将源根添加到 python 路径”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-31
        • 2014-10-10
        • 2014-09-20
        • 2014-08-28
        • 2014-06-10
        • 2016-05-16
        • 2019-05-25
        相关资源
        最近更新 更多