Celery: add_periodic_task рдлрд╝рдВрдХреНрд╢рди рдХрд╛рд░реНрдп рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 13 рдирд╡ре░ 2016  ┬╖  33рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: celery/celery

рдЬрд╛рдВрдЪ рд╕реВрдЪреА

  • [x] рдореИрдВрдиреЗ рдирд┐рд░реНрдЧрдо рдореЗрдВ celery -A proj report рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рд╣реИред
    (рдпрджрд┐ рдЖрдк рдРрд╕рд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдХрдо рд╕реЗ рдХрдо рдЕрдЬрд╡рд╛рдЗрди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ
    рд╕рдВрд╕реНрдХрд░рдг рдкреНрд░рднрд╛рд╡рд┐рдд)ред
  • [x] рдореИрдВрдиреЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдпрд╛ рд╣реИ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдХреА master рд╢рд╛рдЦрд╛ рдХреЗ рдЦрд┐рд▓рд╛рдл рдпрд╣ рдореБрджреНрджрд╛ рдореМрдЬреВрдж рд╣реИред

рдкреНрд░рдЬрдирди рдХрд░рдиреЗ рдХрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛

рдХрд╛рд░реНрдп

from celery import Celery

celery = Celery('tasks', broker='pyamqp://guest@localhost//')

@celery.task
def add(x, y):
    return x + y


@celery.on_after_configure.connect
def add_periodic():
    celery.add_periodic_task(10.0, add.s(2,3), name='add every 10')

if __name__ == '__main__':
        add_periodic()


рдЪрд░рдг 1: рдЦрд░рдЧреЛрд╢рдмреАрдо рдКрдкрд░ рд╣реИ
рдЦрд░рдЧреЛрд╢ 1186 1 0 Nov12? 00:00:00 / рдмрд┐рди / рд╢ / usr / sbin / rabbitmq- рд╕рд░реНрд╡рд░

рдЪрд░рдг 2: рдЯрд╛рд╕реНрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ
python tasks.py
рд╕реНрдЯреЗрдк 3: рдмреАрдЯ рд╡рд░реНрдХрд░ рд╢реБрд░реВ рдХрд░реЗрдВ
celery -A tasks -l info beat
рдЕрдЬрд╡рд╛рдЗрди рдмреАрдЯ v4.0.0 (рдЕрд╡реНрдпрдХреНрдд) рд╢реБрд░реВ рд╣реЛ рд░рд╣рд╛ рд╣реИред
__ - ... __ - _
рд╕реНрдерд╛рдиреАрдп рд╕рдордп -> 2016-11-12 17:37:58
рд╡рд┐рдиреНрдпрд╛рд╕ ->
ред рджрд▓рд╛рд▓ -> amqp: // рдЕрддрд┐рдерд┐: ** @localhost : 5672 //
ред рд▓реЛрдбрд░ -> celery.loaders.app.AppLoader
ред рдЕрдиреБрд╕реВрдЪрдХ
ред db -> рд╕реЗрд▓реЗрд░реАрдмреАрдЯ-рд╢реЗрдбреНрдпреВрд▓
ред logfile -> [stderr] @% INFO
ред рдЕрдзрд┐рдХрддрдо рд▓рдВрдмрд╛рдИ -> 5.00 рдорд┐рдирдЯ (300s)
[реирежрезрем-резрез-резреи рез 2016: рей 58: рел,9 реп резреи: рдЗрдиреНрдлреЛ / рдореЗрдирдкреНрд░реЛрд╕реЗрд╕] рдмреАрдЯ: рд╢реБрд░реВ ...

рдЕрдкреЗрдХреНрд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЕрдиреБрд╕реВрдЪрдХ рд╣рд░ рджрд╕ рд╕реЗрдХрдВрдб рдореЗрдВ рдРрдб () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░реЗрдЧрд╛ред

рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡реНрдпрд╡рд╣рд╛рд░

рдРрдб () рдлрд╝рдВрдХреНрд╢рди рдЯреНрд░рд┐рдЧрд░ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рдореБрдЭреЗ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдХреЛрдИ рдЕрдкрд╡рд╛рдж рдирд╣реАрдВ рджрд┐рдЦ рд░рд╣рд╛ рд╣реИред рдХреНрдпрд╛ рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рд╣реИ?

Celerybeat Bug Report

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЖрд╡рдзрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ -B рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╕рдордп рдЕрдиреБрд╕реВрдЪрдХ рдХреЛ рднреА рдЖрдордВрддреНрд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

celery -A proj worker -B

Django рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ, рдЬрд╣рд╛рдВ рдХрд╛рд░реНрдп рдХреНрд╖реБрдзрд╛ рд╕реЗ autodiscovered рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ on_after_finalize рдХреЗ рдмрдЬрд╛рдп рд╕рдВрдХреЗрдд on_after_configure ред

рд╕рдВрджрд░реНрдн:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django

рд╕рднреА 33 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореБрдЭреЗ рднреА рдпрд╣реА рд╕рдорд╕реНрдпрд╛ рдереА :(

рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рдореЗрд░реЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдиреЛрдЯ: рдЖрдкрдХреЗ рд╕рд┐рдЧреНрдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЛ ** kwargs рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдРрд╕рд╛ рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рд╣реЛрдирд╛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╣реЛрдЧреАред

рдЕрдкрдиреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛

# file: tasks.py
from celery import Celery

celery = Celery('tasks', broker='pyamqp://guest@localhost//')

@celery.task
def add(x, y):
    return x + y


@celery.on_after_configure.connect
def add_periodic(**kwargs):
    celery.add_periodic_task(10.0, add.s(2,3), name='add every 10')

рдореИрдВ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╕реЗ рдмреАрдЯ рд╕реЗрд╡рд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реВрдВ:

$ celery -A tasks beat -l debug
celery beat v4.0.0 (latentcall) is starting.
__    -    ... __   -        _
LocalTime -> 2016-12-01 11:54:56
Configuration ->
    . broker -> amqp://guest:**<strong i="11">@localhost</strong>:5672//
    . loader -> celery.loaders.app.AppLoader
    . scheduler -> celery.beat.PersistentScheduler
    . db -> celerybeat-schedule
    . logfile -> [stderr]@%DEBUG
    . maxinterval -> 5.00 minutes (300s)
[2016-12-01 11:54:56,511: DEBUG/MainProcess] Setting default socket timeout to 30
[2016-12-01 11:54:56,511: INFO/MainProcess] beat: Starting...
[2016-12-01 11:54:56,517: DEBUG/MainProcess] Current schedule:
<ScheduleEntry: celery.backend_cleanup celery.backend_cleanup() <crontab: 0 4 * * * (m/h/d/dM/MY)>
<ScheduleEntry: add every 10 tasks.add(2, 3) <freq: 10.00 seconds>
[2016-12-01 11:54:56,517: DEBUG/MainProcess] beat: Ticking with max interval->5.00 minutes
[2016-12-01 11:54:56,528: DEBUG/MainProcess] Start from server, version: 0.9, properties: {'information': 'Licensed under the MPL.  See http://www.rabbitmq.com/', 'product': 'RabbitMQ', 'copyright': 'Copyright (C) 2007-2016 Pivotal Software, Inc.', 'capabilities': {'exchange_exchange_bindings': True, 'connection.blocked': True, 'authentication_failure_close': True, 'direct_reply_to': True, 'basic.nack': True, 'per_consumer_qos': True, 'consumer_priorities': True, 'consumer_cancel_notify': True, 'publisher_confirms': True}, 'cluster_name': 'rabbit<strong i="12">@grain</strong>', 'platform': 'Erlang/OTP', 'version': '3.6.4'}, mechanisms: [u'AMQPLAIN', u'PLAIN'], locales: [u'en_US']
[2016-12-01 11:54:56,531: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.add)
[2016-12-01 11:54:56,534: DEBUG/MainProcess] using channel_id: 1
[2016-12-01 11:54:56,535: DEBUG/MainProcess] Channel open
[2016-12-01 11:54:56,537: DEBUG/MainProcess] beat: Synchronizing schedule...
[2016-12-01 11:54:56,537: DEBUG/MainProcess] tasks.add sent. id->af224838-cf72-4d0d-9076-1c39cdbeffb8
[2016-12-01 11:54:56,537: DEBUG/MainProcess] beat: Waking up in 9.97 seconds.
[2016-12-01 11:55:06,519: INFO/MainProcess] Scheduler: Sending due task add every 10 (tasks.add)
[2016-12-01 11:55:06,520: DEBUG/MainProcess] tasks.add sent. id->907cf307-e36f-455a-97a8-441c79b8ab92

рдирдорд╕реНрддреЗ, рдореИрдВ рдПрдХ рд╣реА рдореБрджреНрджрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рдереНрд░реЗрдб рдореЗрдВ рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЬрд╛рдПред рд╢рд╛рдпрдж рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рд╣реИред

рдпрд╣ рдореЗрд░рд╛ рдзрд╛рдЧрд╛ рд╣реИ:

from __future__ import absolute_import, unicode_literals
import threading
from celery import current_app
from celery.bin import worker

app = current_app._get_current_object()


class CeleryThread(threading.Thread):
    def __init__(self):
        super(CeleryThread, self).__init__()

        self.app = app
        self.worker = worker.worker(app=self.app)

        self.options = {
            'broker': 'amqp://guest:guest<strong i="7">@localhost</strong>:5672//',
            'loglevel': 'INFO',
            'traceback': True,
        }

        app.add_periodic_task(5.0, test.s('hello'), name='add every 10')

    def run(self):
        self.worker.run(**self.options)


@app.task
def test(args1):
    print args1

рдФрд░ рдЗрд╕реЗ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП main.py

celery_thread = CeleryThread()
# used to kill the thread when the main program stop
# celery_thread.daemon = True
celery_thread.start()

рдореЗрд░рд╛ рдХрдВрд╕реЛрд▓ рдЖрдЙрдЯрдкреБрдЯ рд╣реИ

 -------------- celery<strong i="14">@ubuntu</strong> v4.0.0 (latentcall)
---- **** ----- 
--- * ***  * -- Linux-4.4.0-51-generic-x86_64-with-Ubuntu-16.04-xenial 2016-12-03 14:33:10
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .> app:         default:0x7f75775bfc50 (.default.Loader)
- ** ---------- .> transport:   amqp://guest:**<strong i="15">@localhost</strong>:5672//
- ** ---------- .> results:     disabled://
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery


[tasks]
  . kalliope.core.CrontabManager2.CeleryThread.test

[2016-12-03 14:33:10,458: INFO/MainProcess] Connected to amqp://guest:**@127.0.0.1:5672//
[2016-12-03 14:33:10,466: INFO/MainProcess] mingle: searching for neighbors
[2016-12-03 14:33:11,486: INFO/MainProcess] mingle: all alone
[2016-12-03 14:33:11,515: INFO/MainProcess] celery<strong i="16">@ubuntu</strong> ready.

рдХреНрдпрд╛ рдореИрдВ рдПрдХ рд╡рд┐рдХрд▓реНрдк рднреВрд▓ рд╕рдХрддрд╛ рд╣реВрдБ? рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдкрдХреЗ рдЖрдЙрдЯрдкреБрдЯ @ рдорд╛рд╕реНрдХ рдореЗрдВ "рд╢реЗрдбреНрдпреВрд▓рд░" рд╕реЗрдЯ рд╣реИ

рдХрд┐рд╕реА рднреА рдорджрдж рдХреЗ рд▓рд┐рдП рдЕрдЧреНрд░рд┐рдо рдзрдиреНрдпрд╡рд╛рджред

@ Liuallen1981 рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рд╡рд┐рдиреНрдпрд╛рд╕ рдФрд░ рдПрдХ рд╣реА рдореБрджреНрджрд╛ред рдХрд┐рд╕реА рдХреЛ рднреА рдкрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдЕрднреА рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛

celery.conf.beat_schedule = {
    'do-something-periodically': {
        'task': 'tasks.my_task',
        'schedule': 3.0,
    },
}

on_after_configure.connect рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд╕рд╛рде setup_periodic_tasks рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдпред

+1 рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИред

+1 рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИред
рдЕрдЬрд╡рд╛рдЗрди рд╕рдВрд╕реНрдХрд░рдг 4.0.2 (рдЕрд╡реНрдпрдХреНрдд)

+1 рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИред

+1 рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдкрд░ рдЧрдпрд╛ рдФрд░ @ liuallen1981 рдХреЗ рдХреЛрдб рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рдФрд░ рдореЗрд░реЗ рдЕрдкрдиреЗ рдХреЛрдб рдХреЗ рд╕рдорд╛рди рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ред

рдЕрдЬрд╡рд╛рдЗрди: 4.0.2

рдЖрд╡рдзрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ -B рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╕рдордп рдЕрдиреБрд╕реВрдЪрдХ рдХреЛ рднреА рдЖрдордВрддреНрд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

celery -A proj worker -B

Django рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ, рдЬрд╣рд╛рдВ рдХрд╛рд░реНрдп рдХреНрд╖реБрдзрд╛ рд╕реЗ autodiscovered рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ on_after_finalize рдХреЗ рдмрдЬрд╛рдп рд╕рдВрдХреЗрдд on_after_configure ред

рд╕рдВрджрд░реНрдн:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django

-B рдЙрддреНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╣реИ рдФрд░ рдмрд╕ рдмреАрдЯреНрд╕ рд╢реЗрдбреНрдпреВрд▓рд░ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрдо рд╕реЗ рдХрдо рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЪрд▓ рд░рд╣рд╛ рд╣реИред

+1 рд╕реЗрд▓реЗрд░реА рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдореБрджреНрджрд╛ рд░рд╣рд╛ (4.0.2)

рд╡рд╣реА рдореБрджреНрджрд╛ рдпрд╣рд╛рдБтАжред

рдЖрдк рдмрд╕ рдПрдХ рдмреАрдЯ рд╕реЗрд╡рд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рднреА рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

+1

рдпрд╣рд╛рдБ рдПрдХ рд╣реА рдореБрджреНрджрд╛ рд╣реИ

рдпрд╣рд╛рдБ рдПрдХ рд╣реА рдореБрджреНрджрд╛,

рдФрд░ рдореИрдВ рдХреЙрд▓рдмреИрдХ рдХреЗ рдЕрдВрджрд░ рдХреБрдЫ рдкреНрд░рд┐рдВрдЯ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реВрдВ, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХреЙрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди RabbitMQ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ (рдареАрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рдореИрдВ рдХреЛрдб рдореЗрдВ рдПрдХ рдХрд╛рд░реНрдп рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реВрдВ)

@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
    print('after connect')
(py35) тЮЬ  celery -A celery.beat beat
celery beat v4.0.2 (latentcall) is starting.
__    -    ... __   -        _
LocalTime -> 2017-08-08 02:42:18
Configuration ->
    . broker -> amqp://**:**@**:5672//
    . loader -> celery.loaders.app.AppLoader
    . scheduler -> celery.beat.PersistentScheduler
    . db -> celerybeat-schedule
    . logfile -> [stderr]@%WARNING
    . maxinterval -> 5.00 minutes (300s)

рдореИрдВ рдЗрд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ add_periodic_task celery.conf.beat_schedule рдмрдЬрд╛рдп Celery config

рдореИрдВрдиреЗ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдХрджрдо рд░рдЦрд╛ рдФрд░ рдкрд╛рдпрд╛ рдХрд┐ on_after_configure рд╕рд┐рдЧреНрдирд▓ рдирд┐рдХрд╛рд▓ рджрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдореЗрд░рд╛ рд╕рд┐рдЧреНрдирд▓ рд╢реНрд░реЛрддрд╛ рдмрдирд╛рдпрд╛ / рд╕рдВрд▓рдЧреНрди рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рдерд╛ред (рдореИрдВ рдЕрдкрдиреЗ рд╕рд┐рдЧреНрдирд▓ рд╢реНрд░реЛрддрд╛ рдХреЛ app/tasks.py рдореЗрдВ рд░рдЦ рд░рд╣рд╛ рдерд╛ рдФрд░ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рдерд╛ред)

рдореИрдВрдиреЗ рддрд░реНрдХ рджрд┐рдпрд╛ рдХрд┐ Django рдХрд╛ рдРрдк рд░реЗрдбреА рд╕рд┐рдЧреНрдирд▓ рд╢рд╛рдпрдж рд╕реЗрд▓реЗрд░реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рдмрд╛рдж рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдЧрд╛ рдФрд░ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдм рддрдХ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ: рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рд╡рд┐рдиреНрдпрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣реА рдРрдк рдЖрдЧ рд▓рдЧрд╛ рд╕рдХрддрд╛ рд╣реИ ... рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдХрдо рд╕реЗ рдХрдо рдПрдХ рд░рдирдЯрд╛рдЗрдо рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХ рджреЗрдЧрд╛ред

рдирдореВрдирд╛ рдХреЛрдб рдореЗрд░реЗ app/apps.py :

from django.apps import AppConfig
import django.db.utils
from celery_app import app as celery_app
from celery.schedules import crontab
import utils.cron


class MyAppConfig(AppConfig):
    name = 'app'
    verbose_name = "MyApp"

    def ready(self):
        print("MyAppConfig.ready invoked.")
        import app.signals

        print("* * * Setting up periodic tasks!")
        import app.models
        import app.tasks
        for cron in app.models.CronTask.objects.all():
            celery_app.add_periodic_task(
                crontab(**utils.cron.parse_crontab_expression_to_celery(cron.frequency)),
                app.tasks.do_cron.s(cron.id),
                name='do cron'
            )

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рдирдП AppConfig рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП INSTALLED_APPS рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ settings.py :

INSTALLED_APPS = [
    # ...
    'app.apps.MyAppConfig',
]

рдПрдХ рдЕрдЪреНрдЫрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдпрд╛ рдлрд┐рдХреНрд╕ рд╢рд╛рдпрдж рдПрдХ рдирдпрд╛ рдбреЗрдХреЛрд░реЗрдЯрд░ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ 1) рдЪреЗрдХ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд░ рд╕реЗрд▓реЗрд░реА рдкрд╣рд▓реЗ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдпрджрд┐ рддреБрд░рдВрдд рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ 2) рдпрджрд┐ рд╕реЗрд▓реЗрд░реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рддреЛ @celery.on_after_configure.connect рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╢реНрд░реЛрддрд╛ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред

рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдЦрдбрд╝рд╛ рд╣реИ, рдбреЙрдХреНрд╕ рд╕рдорд╕реНрдпрд╛рдЧреНрд░рд╕реНрдд рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдореЗрдВ рд╕реЗ рдХрдИ рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧ рдЧрдП рдереЗред

CCing @rustanacexd @viennadd рдмрд╕ рдЖрдк рдЗрд╕ рдлрд╝рд┐рдХреНрд╕ рдХреЛ рдЖрдЬрд╝рдорд╛ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЛ рдЕрднреА рднреА рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рд╢реЗрдбреНрдпреВрд▓ рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

рдЕрдкрдиреЗ рджреЛ рд╕реЗрдВрдЯ рдХреЛ рд╡рд╣рд╛рдБ рд▓рдЧрд╛рдХрд░, рдореИрдВ рдЗрд╕рд╕реЗ рдереЛрдбрд╝рд╛ рд╕рдВрднрд▓ рдЧрдпрд╛ рдФрд░ рдЕрдкрдиреЗ рдХреБрдЫ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓рдЧрднрдЧ 8 рд╢реЗрдбреНрдпреВрд▓ рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдп рд╣реИрдВ рдЬреЛ рдЖрдЧ рд▓рдЧрдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реЛрдЧрд╛:

рдЙрджрд╛рд╣рд░рдг:

@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
    celery.add_periodic_task(5.0, do_thing_b.s(), name='Test B')
    celery.add_periodic_task(4.9, do_thing_a.s(), name='Test A')

рдЙрдиреНрд╣реЗрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЖрджреЗрд╢ рджреЗрдиреЗ рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ do_thing_a рдХрднреА рднреА рдЖрдЧ рдирд╣реАрдВ рд▓рдЧреЗрдЧреА, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ do_thing_b рджреНрд╡рд╛рд░рд╛ рдЕрдзрд┐рд▓реЗрдЦрд┐рдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдореВрд▓ рд░реВрдк рд╕реЗ рд╡реЗ рджреЛрдиреЛрдВ 5 рд╕реЗрдЯ рдереЗ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдЖрдЧ рд▓рдЧрд╛рдПрдЧрд╛ (рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдмреА рд╣реЛрдЧрд╛ рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛)ред рдЗрд╕рдХреЗ рдмрд╛рдж рдореИрдВрдиреЗ рдЬреЛ рдХрд┐рдпрд╛ рдЙрд╕реЗ рджрд╢рдорд▓рд╡ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдФрд░ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдЗрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП .1 рднрд░рдкрд╛рдИ рдХрд░реЗрдВрдЧреЗред рдХреЛрдИ рдкрд╛рдБрд╕рд╛ рдирд╣реАрдВред рддрдм рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ рдЖрджреЗрд╢ рджрд┐рдпрд╛ рдХрд┐ рдиреАрдЪреЗ рд╡рд╛рд▓рд╛ рдкрд╣рд▓реЗ рдлрд╛рдпрд░ рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрдЪреНрдЪрддрд░ рджреВрд╕рд░рд╛ рдлрд╛рдпрд░ рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрд╕рдиреЗ рдЗрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛ред рдЕрд░реНрдерд╛рдд:

@celery.on_after_configure.connect
def setup_periodic_tasks(**kwargs):
    celery.add_periodic_task(4.9, do_thing_b.s(), name='Test B')
    celery.add_periodic_task(5.0, do_thing_a.s(), name='Test A')

рд╣рдо рдХреБрдЫ crontab() s рдХрд╛ рдЙрдкрдпреЛрдЧ рднреА рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реЗ рдХреБрдЫ рдХрд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд╣рд╕реНрдп рдХреА рддрд░рд╣ рд╣реИрдВ рдФрд░ рдХреБрдЫ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдореБрдЭреЗ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдКрдкрд░ рдХреЗ рд╕рдорд╛рди рд╣реА рдореБрджреНрджрд╛ рд╣реИред рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рдЦреЗрд▓ рдкрд╛рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпреЗ рдЕрдВрддрд░рд╛рд▓ рдЖрдо рддреМрд░ рдкрд░ рд╣рд░ X рдШрдВрдЯреЗ / рджрд┐рди рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЖрдорддреМрд░ рдкрд░ рднреВрд▓ рдЬрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рд╡реЗ рдореМрдЬреВрдж рд╣реИрдВред

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬреАрдХрд░рдг рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛ, рдпрд╛ рдореИрдВ рдПрдХ рдЕрд▓рдЧ рдЦрд░рдЧреЛрд╢ рдХреЗ рдЫреЗрдж рдХреЗ рдиреАрдЪреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдмрд╣реБрдд рдорддрд▓рдм рдирд╣реАрдВ рд╣реИред рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП, рд╣рдо RMQ рдФрд░ рдЕрдЬрд╡рд╛рдЗрди 4.1.0 рдХреЗ рдмрдЬрд╛рдп Redis рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рдореИрдВ рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ред рдореЗрд░рд╛ рдЬрд╡рд╛рдм рдпрд╣рд╛рдВ рджреЗрдЦреЗрдВ:

https://stackoverflow.com/a/46965132/560945

@ prasanna-balaraman рдЬреЛ рдХрд╛рдо рдХрд░рдиреЗ рд▓рдЧрддрд╛ рд╣реИ, рд╕реБрдЭрд╛рд╡ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!

рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рд╣реА рдореБрджреНрджрд╛: рдореИрдВ рдПрдХ рдФрд░ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реВрдВрдЧрд╛: https://stackoverflow.com/a/41119054/6149867

рд╕рдорд╛рдкрдиред рдЕрдЧрд░ рдпрд╣ рдЕрднреА рднреА рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ рдФрд░ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдХреЛрдб рдпрд╛ рдбреЙрдХреНрд╕ рд╕реБрдЭрд╛рд╡ рд╣реИрдВ, рддреЛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреАрдЖрд░ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред

рдореБрдЭреЗ рдпрд╣ рдорд╣рд╕реВрд╕ рдХрд░рдиреЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рдордп рд▓рдЧрд╛ рдХрд┐ рдпрджрд┐ setup_periodic_tasks рдореЗрдВ рдХреЛрдИ рдЕрдкрд╡рд╛рдж рдЙрдард╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдЪреБрдкрдЪрд╛рдк рджрдмрд╛ рд╣реБрдЖ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред

рд╕рдорд╛рд░реЛрд╣ рдХреЛ рдпрд╣рд╛рдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: https://github.com/celery/celery/blob/master/celery/app/base.py#L950

рдпрджрд┐ рдХреБрдЫ рднреА рдЧрд▓рдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЕрдкрд╡рд╛рдж рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЛрдИ рдкреБрди: рдмрдврд╝рд╛ рдпрд╛ рд▓реЙрдЧ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ:
https://github.com/celery/celery/blob/master/celery/utils/dispatch/signal.py#L276

рдЗрд╕рд▓рд┐рдП рдореЗрд░рд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ рдХрд┐ setup_periodic_tasks рдХреЛ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд░рдЦреЗрдВред
рдЙрдореНрдореАрдж рд╣реИ рдХреА рдпрд╣ рдорджрдж рдХрд░реЗрдЧрд╛!

@ chiang831 рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЗрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕реБрдЭрд╛рд╡ рд╣реИ? рдпрджрд┐ рдРрд╕рд╛ рд╣реИ рддреЛ plz рдПрдХ рдЬрдирд╕рдВрдкрд░реНрдХ рднреЗрдЬреЗрдВ рдпрд╛ рдЕрдЬрд╡рд╛рдЗрди-рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЗрд▓рд┐рдВрдЧ рд╕реВрдЪреА рдкрд░ рдЪрд░реНрдЪрд╛ рдЦреЛрд▓реЗрдВ

on_after_finalize рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рдЧреИрд░-рдбреАрдЬреЗрдВрдЧреЛ рдЕрдЬрд╡рд╛рдЗрди рдРрдк)ред

@app.on_after_finalize.connect
def app_ready(**kwargs):
    """
    Called once after app has been finalized.
    """
    sender = kwargs.get('sender')

    # periodic tasks
    speed = 15
    sender.add_periodic_task(speed, update_leases.s(),
        name='update leases every {} seconds'.format(speed))

рдмрд╕ рдЗрд╕ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ рдФрд░ рдкрд┐рдЫрд▓реЗ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдЗрд╕рдХреЗ рдХрд╛рд░рдг рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рдЯреАрдХ рдкрд░рд┐рджреГрд╢реНрдп рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ рдФрд░ рд░реЗрдл-рдХрд╛рдЙрдВрдЯрд┐рдВрдЧ / gc рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдФрд░ рдЖрдкрдХреЗ рд╕рдЬрд╛рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рдЯреАрдХ рдЬреАрд╡рдирдХрд╛рд▓ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВред

рд╕рд┐рдЧреНрдирд▓.рдХрдиреЗрдХреНрдЯ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдХреЗрд╡рд▓ рд╕рд┐рдЧреНрдирд▓ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдордЬреЛрд░ рд╕рдВрджрд░реНрдн рд░рдЦрддрд╛ рд╣реИред рдпрд╣ рд╕рд┐рдЧреНрдирд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ (рдПрдХ рдЫреЛрдЯреА рдЬреАрд╡рд┐рдд рд╡рд╕реНрддреБ рдЬреЛ рддрд╛рд░реЛрдВ рдХреЗ рд╕рд┐рдЧреНрдирд▓ рдХреЛ рдЙрд╕рдХреЗ рд╕рд┐рдЧреНрдирд▓ рд╣реИрдВрдбрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдЬреАрд╡рд┐рдд рдирд╣реАрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП), рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдмрд╣реБрдд рдЖрд╢реНрдЪрд░реНрдп рдХреА рдмрд╛рдд рд╣реИред

рдореЗрд░рд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдирдП рдЖрд╡рдзрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рдерд╛:

def call_every_5_min(task):
    @app.on_after_configure.connect
    def register_task(sender, **_):
        sender.add_periodic_task(collect_every_m*60, task.signature())

<strong i="8">@call_every_5_min</strong>
<strong i="9">@task</strong>
def my_celery_task(_):
     pass

рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ рдордЬрдмреВрдд рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдкреВрдЫрдирд╛ рд╣реИ:

def call_every_5_min(task):
    def register_task(sender, **_):
        sender.add_periodic_task(collect_every_m*60, task.signature())
    app.on_after_configure.connect(register_task, weak=False)

рдбреЙрдХреНрд╕ рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рдХреЗрд╡рд▓ рддрднреА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рдЖрдкрдХрд╛ рд╕рдЬрд╛рдпрд╛ рдЧрдпрд╛ рдлрд╝рдВрдХреНрд╢рди рдореЙрдбреНрдпреВрд▓ рдпрд╛ рдХреНрд▓рд╛рд╕ рд╕реНрдХреЛрдк рдкрд░ рд╣реЛ, рдЬрд┐рд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдореЙрдбреНрдпреВрд▓ рдпрд╛ рдХреНрд▓рд╛рд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдордЬрдмреВрдд рд╕рдВрджрд░реНрдн рд░рдЦрддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛ рдХреЗрд╡рд▓ рдордЬрдмреВрдд рд╕рдВрджрд░реНрдн рдЙрд╕ рджрд╛рдпрд░реЗ рдХреЗ рдЕрдВрдд рдореЗрдВ рдорд░ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рдЗрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдореИрдВ weak=False рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХреНрд╕ рдмрджрд▓рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ, рдЬреЛ рдКрдкрд░ рд╕реВрдЪреАрдмрджреНрдз рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдореИрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдХ Django рд╕рдВрджрд░реНрдн рдореЗрдВ рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред

рдЖрд╡рдзрд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ -B рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╕рдордп рдЕрдиреБрд╕реВрдЪрдХ рдХреЛ рднреА рдЖрдордВрддреНрд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

celery -A proj worker -B

Django рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ, рдЬрд╣рд╛рдВ рдХрд╛рд░реНрдп рдХреНрд╖реБрдзрд╛ рд╕реЗ autodiscovered рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ on_after_finalize рдХреЗ рдмрдЬрд╛рдп рд╕рдВрдХреЗрдд on_after_configure ред

рд╕рдВрджрд░реНрдн:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django

рдореЗрд░реЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ python -m celery -A app_name worker -l info --autoscale=20,5 -BE рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрд╡рд░реБрджреНрдз app_name.celery.py рдЬрдм рдХрд╛ рдЙрдкрдпреЛрдЧ on_after_finalize ред

@ Liuallen1981 рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рд╡рд┐рдиреНрдпрд╛рд╕ рдФрд░ рдПрдХ рд╣реА рдореБрджреНрджрд╛ред рдХрд┐рд╕реА рдХреЛ рднреА рдкрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдЕрднреА рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛

celery.conf.beat_schedule = {
    'do-something-periodically': {
        'task': 'tasks.my_task',
        'schedule': 3.0,
    },
}

on_after_configure.connect рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд╕рд╛рде setup_periodic_tasks рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдпред

рдпрд╣ рдореЗрд░реЗ рдмрджрд▓реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдпрджрд┐ рдЖрдк рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдкрд╣рд▓реЗ рдЕрдкрдиреЗ рдбреЙрдХ рдЗрдВрдЬрди рдХреЛ рд░рд┐рдмреВрдЯ рдХрд░реЗрдВ, рдпрд╣ рд╕рд┐рдЧреНрдирд▓ рдмрдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ

рдХреНрдпрд╛ рд╣рдореЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдмрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП?

@ рдпреБрд╡реАрдкреА рдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВред рд▓рдЧрддрд╛ рд╣реИ рдпрд╣ рдЕрдЬрд╡рд╛рдЗрди рдмрдЧ рд╣реИ

рдпрд╣ рдПрдХ рдмрдЧ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдореЗрдВ рдареАрдХ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

asmodehn picture asmodehn  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

Xuexiang825 picture Xuexiang825  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

budlight picture budlight  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

steinliber picture steinliber  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

aTylerRice picture aTylerRice  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ