对于那些发现celery 4.0.1文档中描述的定期任务声明难以集成到django中的人来说,这不是一个问题,而是帮助: http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html#entries
复制粘贴芹菜配置文件main_app/celery.py
:
from celery import Celery
from celery.schedules import crontab
app = Celery()
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')
# Calls test('world') every 30 seconds
sender.add_periodic_task(30.0, test.s('world'), expires=10)
# Executes every Monday morning at 7:30 a.m.
sender.add_periodic_task(
crontab(hour=7, minute=30, day_of_week=1),
test.s('Happy Mondays!'),
)
@app.task
def test(arg):
print(arg)
但是如果我们使用django并将我们的任务放在另一个应用程序中呢?对于芹菜4.0.1
,我们不再拥有@periodic_task
装饰器。那么让我们看看我们能做些什么。
如果您希望保持任务及其日程安排彼此接近:
main_app/some_app/tasks.py
from main_app.celery import app as celery_app
@celery_app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, test.s('hello'))
@celery_app.task
def test(arg):
print(arg)
我们可以在调试模式下运行beat
:
celery -A main_app beat -l debug
我们将看到没有这样的定期任务。
我们可以尝试在配置文件中描述所有周期性任务,如下所示:
main_app/celery.py
...
app = Celery()
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
from main_app.some_app.tasks import test
sender.add_periodic_task(10.0, test.s('hello'))
...
结果是一样的。但是通过pdb手动调试可以看到它的行为方式不同。在第一个示例中,setup_periodic_tasks
将不会触发回调。但在第二个例子中,我们将获得django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
(此异常不会被打印出来)
答案 0 :(得分:22)
对于django,我们需要使用另一个信号:@celery_app.on_after_finalize.connect
。它可以用于:
app/tasks.py
中的任务,因为此信号将在所有tasks.py
导入和所有可能的已接收订阅者(第一种情况)之后被触发。我想我应该写下最后的声明:
接近任务的任务计划声明:
main_app/some_app/tasks.py
from main_app.celery import app as celery_app
@celery_app.on_after_finalize.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, test.s('hello'))
@celery_app.task
def test(arg):
print(arg)
配置文件main_app/celery.py
中的集中计划声明:
...
app = Celery()
@app.on_after_finalize.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
from main_app.some_app.tasks import test
sender.add_periodic_task(10.0, test.s('hello'))
...
答案 1 :(得分:7)
如果目的是在tasks.py中单独维护任务逻辑,那么在from main_app.some_app.tasks import test
内调用setup_periodic_tasks
对我来说不起作用。有效的是:
<强> celery.py 强>
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')
@app.task
def test(arg):
print(arg)
from some_app.tasks import test
test(arg)
<强> tasks.py 强>
@shared_task
def test(arg):
print('world')
这导致以下输出:
[2017-10-26 22:52:42,262: INFO/MainProcess] celery@ubuntu-xenial ready.
[2017-10-26 22:52:42,263: INFO/MainProcess] Received task: main_app.celery.test[3cbdf4fa-ff63-401a-a9e4-cfd1b6bb4ad4]
[2017-10-26 22:52:42,367: WARNING/ForkPoolWorker-2] hello
[2017-10-26 22:52:42,368: WARNING/ForkPoolWorker-2] world
[2017-10-26 22:52:42,369: INFO/ForkPoolWorker-2] Task main_app.celery.test[3cbdf4fa-ff63-401a-a9e4-cfd1b6bb4ad4] succeeded in 0.002823335991706699s: None
[2017-10-26 22:52:51,205: INFO/Beat] Scheduler: Sending due task add every 10 (main_app.celery.test)
[2017-10-26 22:52:51,207: INFO/MainProcess] Received task: main_app.celery.test[ce0f3cfc-54d5-4d74-94eb-7ced2e5a6c4b]
[2017-10-26 22:52:51,209: WARNING/ForkPoolWorker-2] hello
[2017-10-26 22:52:51,209: WARNING/ForkPoolWorker-2] world
答案 2 :(得分:0)
我可以使用
celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
app = Celery('mysite')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
tasks.py
from celery import current_app
app = current_app._get_current_object()
@app.task
def test(arg):
print(arg)
@app.on_after_finalize.connect
def app_ready(**kwargs):
"""
Called once after app has been finalized.
"""
sender = kwargs.get('sender')
# periodic tasks
speed = 5
sender.add_periodic_task(speed, test.s('foo'),name='update leases every {} seconds'.format(speed))
以
身份运行工人celery -A mysite worker --beat --scheduler django --loglevel=info
答案 3 :(得分:0)
如果要单独使用任务逻辑,请使用以下设置:
celery.py :
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') # your settings.py path
app = Celery()
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
sender.add_periodic_task(5, periodic_task.s('sms'), name='SMS Process')
sender.add_periodic_task(60, periodic_task.s('email'), name='Email Process')
@app.task
def periodic_task(taskname):
from myapp.tasks import sms_process, email_process
if taskname == 'sms':
sms_process()
elif taskname == 'email':
email_process()
一个名为myapp
的Django应用中的示例任务:
myapp / tasks.py :
def sms_process():
print('send sms task')
def email_process():
print('send email task')