celery -A proj report
en la edición.master
de Apio.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():
celery.add_periodic_task(10.0, add.s(2,3), name='add every 10')
if __name__ == '__main__':
add_periodic()
paso 1: rabbitmq está activo
rabbitmq 1186 1 0 Nov12? 00:00:00 / bin / sh / usr / sbin / rabbitmq-server
paso 2: ejecutar tasks.py
python tasks.py
paso 3: iniciar el trabajador de ritmo
celery -A tasks -l info beat
se está iniciando apio beat v4.0.0 (latentcall).
__ - ... __ - _
LocalTime -> 2016-11-12 17:37:58
Configuración ->
. corredor -> amqp: // invitado: ** @localhost : 5672 //
. cargador -> celery.loaders.app.AppLoader
. planificador -> celery.beat.PersistentScheduler
. db -> celerybeat-schedule
. archivo de registro -> [stderr] @% INFO
. maxinterval -> 5,00 minutos (300 s)
[2016-11-12 17: 37: 58,912: INFO / MainProcess] latido: Iniciando ...
Espero que el programador active la función add () cada diez segundos.
La función add () no se activa.
No veo ninguna excepción en la terminal. ¿Me pierdo algo?
Yo tuve el mismo problema :(
Tu ejemplo me funciona bien.
NOTA: Su manejador de señales debe aceptar ** kwargs, si no lo hace, será un error en el futuro.
Usando tu ejemplo
# 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')
Comienzo el servicio beat de la siguiente manera:
$ 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
Hola, tengo el mismo problema. Pero trato de iniciar el apio mediante programación en un hilo. tal vez sea la causa.
Este es mi hilo:
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
Y el main.py para lanzar este
celery_thread = CeleryThread()
# used to kill the thread when the main program stop
# celery_thread.daemon = True
celery_thread.start()
La salida de mi consola es
-------------- 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.
¿Olvidé una opción? Puedo ver que tiene un "programador" configurado en su salida @ask
Gracias de antemano por cualquier ayuda.
La misma configuración con @ liuallen1981 y el mismo problema. ¿Alguien se da cuenta de lo que está pasando ?. Por ahora tengo que usar
celery.conf.beat_schedule = {
'do-something-periodically': {
'task': 'tasks.my_task',
'schedule': 3.0,
},
}
en lugar de usar una función setup_periodic_tasks
con on_after_configure.connect
decorador.
+1 También tengo este problema.
+1 También tengo este problema.
Apio versión 4.0.2 (latentcall)
+1 También tengo este problema.
+1 También tengo este problema. Seguí y probé con el obtuve el mismo resultado que con mi propio código.
Apio: 4.0.2
Para ejecutar tareas periódicas, debe invocar también el programador al iniciar un trabajador usando la opción -B
:
celery -A proj worker -B
Cuando use apio en aplicaciones de django, donde las tareas se descubren automáticamente desde las aplicaciones, debe usar la señal on_after_finalize
lugar de on_after_configure
.
Referencias:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django
-B no es para producción y simplemente inicia el programador Beats que al menos en mi caso ya se está ejecutando.
+1 tiene el mismo problema con Apio (4.0.2)
El mismo problema aquí ...
usted acaba de iniciar un servicio de ritmo, también debe iniciar un trabajador para hacer la tarea.
+1
mismo problema aquí
mismo problema aquí,
e intento imprimir algo dentro de la devolución de llamada, parece que no se ha llamado a la devolución de llamada, pero RabbitMQ está funcionando (funciona bien cuando activo una tarea en el código)
@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)
Utilizo la configuración de Apio celery.conf.beat_schedule
lugar de dinámicamente add_periodic_task
para resolver esto, ya que no tengo que establecer el horario dinámicamente, pero aún no sé por qué ocurre este problema.
Pasé por la biblioteca y descubrí que mi oyente de señal se estaba creando / adjuntando después de que se disparara la señal on_after_configure
. (Estaba colocando mi oyente de señal en app/tasks.py
y no funcionaba).
Razoné que la señal de preparación de la aplicación de Django probablemente se ejecutaría después de la configuración de Celery y hasta ahora me está funcionando bien.
NOTA: No estoy seguro de lo que realmente implica la configuración de apio y si es posible que app.ready se active antes de que se configure Apio ... sin embargo, espero que al menos arroje un error de tiempo de ejecución.
Código de muestra de mi 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'
)
Tenga en cuenta que también debe señalar INSTALLED_APPS
para usar su nuevo AppConfig
en settings.py
:
INSTALLED_APPS = [
# ...
'app.apps.MyAppConfig',
]
Un buen enfoque o solución probablemente sería escribir un nuevo decorador que 1) verifique si Celery ya está configurado y, si es así, se ejecuta inmediatamente y 2) si Celery no está configurado, agregue el oyente usando @celery.on_after_configure.connect
.
Tal como está, los documentos son problemáticos ya que muchos de nosotros nos encontramos con este problema.
¿ Enviar un CC a @viennadd solo para poder probar esta solución si aún necesita programar tareas dinámicamente?
Poniendo mis dos centavos, me mordió esto y terminé teniendo que reordenar algunas de mis tareas. Tenemos alrededor de 8 tareas programadas que se supone deben activarse, sin embargo, noté que sucedería lo siguiente:
Ejemplo:
@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')
Ordenarlos de esta manera significa que do_thing_a
nunca se activará, ya que se sobrescribirá con do_thing_b
. Originalmente, ambos estaban configurados en 5
, aunque solo uno se dispararía (creo que en este caso habría sido B ya que se agregó primero). A continuación, lo que hice fue cambiarlo a decimal y compensarlo con .1
para ver si eso lo arreglaría. No dados. Luego les ordené que el inferior disparara primero y el superior disparara segundo y eso terminó por arreglarlo. Es decir:
@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')
También estamos usando algunos crontab()
s, aunque es una especie de misterio que se ejecuten, ya que algunos funcionan y otros no, sospecho que es el mismo problema que el anterior. No he jugado completamente con eso, ya que esos intervalos generalmente se establecen para que ocurran cada X horas / días, por lo que generalmente olvido que existen.
Tal vez este tipo de comportamiento se menciona en la documentación, o voy a pasar por una madriguera diferente, aunque este comportamiento no tiene mucho sentido. Como referencia, estamos usando Redis en lugar de RMQ y apio 4.1.0.
Pude hacer que esto funcionara. Mira mi respuesta aquí:
@ prasanna-balaraman Eso parece funcionar, ¡gracias por la sugerencia!
El mismo problema para mí: probaré la otra solución: https://stackoverflow.com/a/41119054/6149867
clausura. si todavía aparece y alguien tiene algún código o sugerencia de documentos, no dude en enviar una referencia a este problema.
Me tomó un tiempo darme cuenta de que si se genera alguna excepción en setup_periodic_tasks, se suprimirá silenciosamente.
La función se llama aquí: https://github.com/celery/celery/blob/master/celery/app/base.py#L950
Si algo sale mal, la excepción solo se guarda en las respuestas, no se vuelve a generar ni se registra:
https://github.com/celery/celery/blob/master/celery/utils/dispatch/signal.py#L276
Entonces, mi sugerencia es mantener setup_periodic_tasks lo más simple posible.
¡Espero que esto ayude!
@ chiang831 ¿tiene alguna sugerencia para mejorarlo? si es así, por favor envíe un PR o abra una discusión en la lista de correo de usuarios de apio
Definirlos en on_after_finalize
es lo que funcionó para mí (aplicación de apio que no es de Django).
@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))
Me encontré con esto y ninguna de las soluciones anteriores funcionó para mí. Los escenarios exactos que causan esto son confusos y dependen del comportamiento del recuento de referencias / gc y la duración exacta de sus funciones decoradas.
Signal.connect por defecto solo tiene una referencia débil al manejador de señales. Esto tiene sentido para otros casos de uso del objeto Signal (un objeto de corta duración que conecta las señales no deben mantenerse vivas por sus manejadores de señales), pero es muy sorprendente en este caso.
Mi caso de uso específico fue un decorador para facilitar la adición de nuevas tareas periódicas:
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
La solución es pedir explícitamente una referencia sólida:
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)
El ejemplo en los documentos solo funciona si su función decorada está en el ámbito del módulo o de la clase, en cuyo caso el módulo o la clase continúa teniendo una fuerte referencia a la función. De lo contrario, la única referencia sólida morirá al final del alcance en el que está definida.
Recomiendo cambiar los documentos para pasar weak=False
, que debería funcionar en los casos enumerados anteriormente. Sin embargo, no he probado esto explícitamente en un contexto de Django.
Para ejecutar tareas periódicas, debe invocar también el programador al iniciar un trabajador usando la opción
-B
:
celery -A proj worker -B
Cuando use apio en aplicaciones de django, donde las tareas se descubren automáticamente desde las aplicaciones, debe usar la señal
on_after_finalize
lugar deon_after_configure
.Referencias:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django
Mi proceso de python -m celery -A app_name worker -l info --autoscale=20,5 -BE
bloqueó al final de app_name.celery.py
cuando uso on_after_finalize
.
La misma configuración con @ liuallen1981 y el mismo problema. ¿Alguien se da cuenta de lo que está pasando ?. Por ahora tengo que usar
celery.conf.beat_schedule = { 'do-something-periodically': { 'task': 'tasks.my_task', 'schedule': 3.0, }, }
en lugar de usar una función
setup_periodic_tasks
conon_after_configure.connect
decorador.
En cambio, esto funciona para mí.
Si está tratando de resolver este problema, reinicie primero el motor de la ventana acoplable, puede ser una señal de error del sistema.
¿Deberíamos cerrar este problema como si no fuera un error?
@auvipy no estoy seguro. Parece que es un bicho de apio
Es un error que debemos corregir.
Comentario más útil
Para ejecutar tareas periódicas, debe invocar también el programador al iniciar un trabajador usando la opción
-B
:celery -A proj worker -B
Cuando use apio en aplicaciones de django, donde las tareas se descubren automáticamente desde las aplicaciones, debe usar la señal
on_after_finalize
lugar deon_after_configure
.Referencias:
http://stackoverflow.com/questions/40712678/setup-periodic-task/40727526
http://stackoverflow.com/questions/41119053/connect-new-celery-periodic-task-in-django