0

When executing async task celery is raising an exception

#case where error is thrown
send_registration_email.delay("test", "[email protected]", {})

This error does not appear when I execute code by omitting celery

#case where code is executed correctly
send_registration_email("test", "[email protected]", {})

How can I execute my async task with celery, so I will and get rid of this error ?

Error

[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

Celery Task

# 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 Class

# 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 = "[email protected]"

        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
8
  • 2
    have you restarted your worker since you added the from utilities.helpers.mailer import Mailer ? Commented Oct 12, 2015 at 13:14
  • 1
    I wonder why you've made these part of a class? There really isn't any need for that Mailer class, since it just contains two static/class methods. Make them standalone module-level functions. Commented Oct 12, 2015 at 13:18
  • Hi @grrrrrr. You were very right apparently restarting the worker fixed the issue. I had to restart my supervisor who runs the celery worker. Commented Oct 12, 2015 at 13:31
  • @Daniel Roseman I use Mailer class an aggregate and wrapper for mailing. It allows me to keep in one place all things strictly related to email (tempaltes, subject ..). I believe this is called "separation of concerns" Commented Oct 12, 2015 at 13:34
  • But that is what mailer.py is. Why do you need a second namespace within that? Commented Oct 12, 2015 at 13:36

2 Answers 2

2

You will need to restart your worker in order to see changes to your files reflected in your worker instances. Celery does not monitor for file changes, so if you change any of the files while your workers are running you will need to restart the workers.

For development purposes this can be sidestepped by using the auto reloading feature:

When auto-reload is enabled the worker starts an additional thread that watches for changes in the file system. New modules are imported, and already imported modules are reloaded whenever a change is detected, and if the prefork pool is used the child processes will finish the work they are doing and exit, so that they can be replaced by fresh processes effectively reloading the code.

This is an experimental feature and should only be used in development environments

Sign up to request clarification or add additional context in comments.

Comments

-1

As @grrrrrr suggested restarting the celery worker fixes the issue. In my case celery worker is run by supervisor so I had to restart supervisor.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.