4

I have to schedule a task to run every Monday through Saturday. I downloaded django-celery to accomplish the task. I followed the tutorial on the Celery site and I used and looked at a few stack overflow posts, for example: here & here

I did a mix and match with the above posts and with this two great tutorials: Rhatore and Freitas

This is my folder structure:

Application
    | apps
         | app1
              | __init__.py
              | tasks.py
              | urls.py
              | views.py    
    | Application
         | __init__.py
         | celery.py
         | settings.py
         | urls.py
         | wsgi.py

Settings.py

INSTALLED_APPS = [
    'django_celery_beat',
    'apps.app1',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True    
USE_TZ = True

CELERY_BROKER_URL = 'amqp://localhost'
CELERY_RESULT_BACKEND = 'amqp://localhost'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'UTC'

__init__.py In the init under the Application

from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app

from .celery import app as celery_app

    __all__ = ('celery_app',)

celery.py

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Application.settings')

app = Celery('Application')

app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

tasks.py - for simplicity sake I reduced the task to a simple print command

from celery import shared_task
from celery.utils.log import get_task_logger
from celery.schedules import crontab
from celery.task import periodic_task
from celeryapp.emails import send_feedback_email
from django.http import HttpResponse
from .models import *

logger=get_task_logger(__name__)

@periodic_task(run_every=crontab(hour=21, minute=32, day_of_week=0-5))
def simple_print():
    print("Hello World!")

I ran:

celery -A Application -1 info

And then python manage.py runserver 21:32 UTC passed and it did not print. I expected to see "Hello World" printed at 21:32 UTC in the terminal as per the task specified in tasks.py. It did not print.

I also ran:

celery -A Application worker -l info
celery -A Application beat -l info
python manage.py runserver

in different terminals. It did not execute the task.

Guidance would be much appreciated.

L. P.
  • 165
  • 1
  • 19
  • Can you explain your problem in more detail. Or maybe "it did not print" - is an explanation of problem? What did you expect? – Alex Yu Feb 15 '19 at 22:03
  • Alex thank you for your question. I edited my question. Basically, what I'm trying to do is to print "Hello World" to the terminal using a cron. – L. P. Feb 15 '19 at 22:15
  • If you substitute `print` with file-`write` or `logging.info` or maybe database insert - would you get "Hello World!"? – Alex Yu Feb 15 '19 at 22:21
  • I tried f = open("myfile.txt", "x") and it didn't create a file. – L. P. Feb 15 '19 at 22:46

2 Answers2

1

You need to have both the worker and the beat running, so that celery will know if it has to run a periodic task at a certain time.

Something like this should help you in your local environment.

celery -A Application worker -l info -B

Alternatively, you can start both workers as individual services

celery -A Application worker -l info

celery -A Application beat -l info
Alex
  • 2,356
  • 15
  • 19
  • I tried to use -B and it's saying that -B does not work on Windows. How do I run them individually? Different terminals? Can I be in any directory or do I need to be in the app directory? When do I run manage.py runserver before or after starting the workers? Does it have to be in another terminal window? – L. P. Feb 15 '19 at 23:07
  • 3 terminals / tmux sessions: one for celery worker, one for beat and then one for runserver. – Alex Feb 15 '19 at 23:09
  • I opened 3 windows. Navigated to the Application folder on each of them. Ran the worker, beat, and python manage.py runserver and it did not print. – L. P. Feb 15 '19 at 23:16
  • Might be a problem with timezones or missing configuration. It's pretty tedious debugging without a stacktrace or something else than brief descriptions. – Alex Feb 15 '19 at 23:20
1

The code was correct. The problem was due to the OS. I'm using Windows and Celery 4.0 does not support Windows. This question was very useful: How to Run Celery on Windows. I installed gevent and it worlks now.

pip install gevent
celery -A Application beat -l info
celery -A Application worker -l info -P gevent

If you get another error along the lines of "Fatal error in launcher..." try:

python -m celery -A Application beat -l info
python -m celery -A Application worker -l info -P gevent
L. P.
  • 165
  • 1
  • 19