调用异步任务芹菜时引发异常:“NameError:未定义全局名称*”

Posted

技术标签:

【中文标题】调用异步任务芹菜时引发异常:“NameError:未定义全局名称*”【英文标题】:When calling async task celery is raising Exception : "NameError: global name * is not defined" 【发布时间】:2016-01-09 23:36:12 【问题描述】:

当执行异步任务时 celery 引发异常

#case where error is thrown
send_registration_email.delay("test", "test@gmail.com", )

当我通过省略 celery 执行代码时不会出现此错误

#case where code is executed correctly
send_registration_email("test", "test@gmail.com", )

如何使用 celery 执行我的异步任务,这样我才能摆脱这个错误?

错误

[2015-10-12 14:50:57,176: ERROR/MainProcess] Task tasks.core.email.send_registration_email[5f96bee3-9df7-42ce-b726-c7086e82b954] raised unexpected: NameError("global name 'Mailer' is not defined",)
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/celery/app/trace.py", line 240, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/celery/app/trace.py", line 438, in __protected_call__
    return self.run(*args, **kwargs)
  File "/srv/www/compare/htdocs/tasks/core/email.py", line 6, in send_registration_email
    @shared_task
NameError: global name 'Mailer' is not defined

芹菜任务

# email.py 
from __future__ import absolute_import
from celery import shared_task
from utilities.helpers.mailer import Mailer

@shared_task
def send_registration_email(email_type="", recipient="", data=):
    Mailer.send_email(email_type, recipient, data)

邮件类

# mailer.py
from __future__ import absolute_import
from django.core.mail.message import EmailMultiAlternatives
from django.template.loader import get_template


class Mailer():

    @staticmethod
    def send_email(email_type="", recipient="", data=):
        try:
            email = Mailer.create_email(email_type, recipient, data)
            email.send()
            return True
        except Exception as e:
            return False

    @classmethod
    def create_email(self, email_type, recipient, data):
        subject = ""
        message = ""
        sender_email = "mailgun@xxx.mailgun.org"

        if email_type == "test":
            subject = "Test subject"
            content_html = "<html><body><h1>Test</h1></body></html>"

        email = EmailMultiAlternatives(subject, None, sender_email, [recipient])
        email.attach_alternative(content_html, "text/html")
        return email

【问题讨论】:

自从添加了from utilities.helpers.mailer import Mailer 后,您是否重新启动了工作程序? 我想知道你为什么把这些作为课程的一部分? Mailer 类真的不需要,因为它只包含两个静态/类方法。使它们成为独立的模块级函数。 嗨@grrrrrr。您显然是非常正确的,重新启动工人解决了这个问题。我不得不重新启动运行 celery worker 的主管。 @Daniel Roseman 我使用 Mailer 类作为邮件的聚合和包装器。它使我可以将与电子邮件严格相关的所有内容(模板、主题 ..)保存在一个地方。我相信这被称为“关注点分离” 但这就是 mailer.py 的内容。为什么在其中需要第二个命名空间? 【参考方案1】:

您需要重新启动您的工作人员才能看到您的文件更改反映在您的工作人员实例中。 Celery 不监视文件更改,因此如果您在工作程序运行时更改任何文件,则需要重新启动工作程序。

出于开发目的,这可以通过使用auto reloading 功能来回避:

启用自动重新加载后,工作线程会启动一个额外的线程来监视文件系统的变化。导入新模块,并在检测到更改时重新加载已导入的模块,如果使用 prefork 池,子进程将完成它们正在执行的工作并退出,以便它们可以被新进程替换,从而有效地重新加载代码.

这是一项实验性功能,只能在开发环境中使用

【讨论】:

【参考方案2】:

正如@grrrrrr 建议重新启动芹菜工人解决了这个问题。在我的情况下,芹菜工人由主管运行,所以我不得不重新启动主管。

【讨论】:

以上是关于调用异步任务芹菜时引发异常:“NameError:未定义全局名称*”的主要内容,如果未能解决你的问题,请参考以下文章

将我的查询集 obj 作为参数传递时芹菜引发错误

异步芹菜任务开销

Celery-一个会做异步任务,定时任务的芹菜

芹菜 - 中间的子任务失败后有没有办法继续执行链

Django 学习之Celery(芹菜)

Celery---一个懂得异步任务,延时任务,周期任务的芹菜