Configurar um trabalho agendado?

519

Estou trabalhando em um aplicativo Web usando o Django, e estou curioso para saber se existe uma maneira de agendar um trabalho para ser executado periodicamente.

Basicamente, eu só quero percorrer o banco de dados e fazer alguns cálculos / atualizações de forma automática e regular, mas não consigo encontrar nenhuma documentação para fazer isso.

Alguém sabe como configurar isso?

Para esclarecer: Eu sei que posso configurar um crontrabalho para fazer isso, mas estou curioso para saber se há algum recurso no Django que fornece essa funcionalidade. Eu gostaria que as pessoas pudessem implantar esse aplicativo elas mesmas sem ter que fazer muita configuração (de preferência zero).

Eu considerei desencadear essas ações "retroativamente" simplesmente verificando se um trabalho deveria ter sido executado desde a última vez em que uma solicitação foi enviada ao site, mas espero algo mais limpo.

TM.
fonte
1
Se você é um site de alto desempenho e já usando RabbitMQ aqui está um truque para contornar cron: Usando AMQP fazer cron-como agendamento
Van Gale
Se bem entendi, você precisa agendar algumas tarefas no Django. A melhor coisa que encontro hoje em dia é esta: celery.github.com/celery/index.html
Ali Nikneshan
o que você acha disso? github.com/reavis/django-cron
Domenico Monaco
Tick foi feito apenas para evitar todo esse trabalho. [Aviso] Eu construo carrapato.
Siscia
2
github.com/coleifer/huey Huey precisa de uma menção aqui. É ridiculamente fácil de configurar com o Django.
Brandon Bertelsen

Respostas:

363

Uma solução que empreguei é fazer isso:

1) Crie um comando de gerenciamento personalizado , por exemplo

python manage.py my_cool_command

2) Use cron(no Linux) ou at(no Windows) para executar meu comando nos horários necessários.

Esta é uma solução simples que não requer a instalação de uma pilha AMQP pesada. No entanto, existem boas vantagens em usar algo como o aipo, mencionado nas outras respostas. Em particular, com o Celery, é bom não ter que espalhar a lógica do aplicativo em arquivos crontab. No entanto, a solução cron funciona muito bem para um aplicativo de tamanho pequeno a médio e onde você não deseja muitas dependências externas.

EDITAR:

Na versão posterior do Windows, o atcomando foi descontinuado para Windows 8, Server 2012 e superior. Você pode usar schtasks.exepara o mesmo uso.

**** UPDATE **** Este é o novo link do django doc para escrever o comando de gerenciamento personalizado

Brian Neal
fonte
5
Essa é uma maneira de fazer isso sem serviços externos, mas usando apenas um processo de estrutura django em execução?
14118 sergzach
4
@Brian_Neal django_cron application.
precisa saber é o seguinte
2
Ajude-me a entender como executarei um comando de gerenciamento em um ambiente virtual usando cron no último dia de cada mês.
mmrs151
2
@ergzach Eu segui esse comentário e acontece que existem dois pacotes com esse nome. O django-cron no Google Code e o django-cron no Github . Eles são um pouco diferentes, mas ambos interessantes. Ambos permitem definir crons de uma maneira 'Djangonic'. O primeiro é um pouco mais antigo e tem como objetivo trabalhar sem uma tarefa externa (ou seja, o cron). O segundo, por outro lado, exige que você configure um cron para executar, python manage.py runcronsque executa todos os crons que você definiu e registrou.
Driftcatcher 18/10/12
1
@sergzach Suponho que você esteja se referindo ao primeiro, "django-cron no Google Code". Você está certo sobre isso. Na verdade, é por isso que eu opto pelo segundo, "django-cron no GitHub", porque faz com que você tenha uma instalação / gerenciamento simples do crontab - apenas um crontab, referindo-se ao comando de gerenciamento - mas desde que você esteja usando um processo cron, você evita esse problema de sincronização (até onde eu sei).
Driftcatcher 18/10/12
152

O aipo é uma fila de tarefas distribuída, construída no AMQP (RabbitMQ). Ele também lida com tarefas periódicas de maneira cron (consulte tarefas periódicas ). Dependendo do seu aplicativo, pode valer a pena.

O aipo é muito fácil de configurar com o django ( documentos ) e as tarefas periódicas realmente pulam as tarefas perdidas em caso de inatividade. O aipo também possui mecanismos de nova tentativa, caso uma tarefa falhe.

dln
fonte
51

Temos código aberto o que eu acho que é um aplicativo estruturado. que a solução de Brian acima também alude. Gostaríamos muito de qualquer / todos os comentários!

https://github.com/tivix/django-cron

Ele vem com um comando de gerenciamento:

./manage.py runcrons

Isso faz o trabalho. Cada cron é modelado como uma classe (portanto, é tudo OO) e cada cron é executado em uma frequência diferente e garantimos que o mesmo tipo de cron não seja executado em paralelo (caso os próprios usuários demorem mais tempo do que sua frequência!)

chachra
fonte
5
@chachra Desculpe, eu sei que isso pode ser uma pergunta idiota, mas isso funcionará no Windows atou foi projetado especificamente para trabalhar cron?
Bruno Finger
38

Se você estiver usando um sistema operacional POSIX padrão, use cron .

Se você estiver usando o Windows, use em .

Escreva um comando de gerenciamento do Django para

  1. Descubra em que plataforma eles estão.

  2. Execute o comando "AT" apropriado para seus usuários ou atualize o crontab para seus usuários.

S.Lott
fonte
10
Eu gostaria que fosse agregado ao meu aplicativo django, se possível.
TM.
@TM: O que significa "agregado ao meu aplicativo django"? Esclareça sua pergunta.
214/09 S.Lott
10
Eu gostaria que as pessoas pudessem implantar facilmente esse aplicativo sem precisar configurar os trabalhos cron.
TM.
1
Você sempre pode agrupar a interface cron em seu aplicativo.
monkut
BSD, Mac e qualquer sistema operacional semelhante ao Unix tem cron.
precisa saber é o seguinte
23

Interessante novo aplicativo Django conectável: django-chronograph

Você só precisa adicionar uma entrada cron que atue como um cronômetro, e você tem uma ótima interface de administração do Django nos scripts para executar.

Van Gale
fonte
2
O django-cronógrafo não é mantido. É do garfo está fazendo muito melhor: github.com/chrisspen/django-chroniker
Menda
16

Veja o Django Poor Man's Cron, que é um aplicativo Django que utiliza spambots, robôs de indexação de mecanismos de pesquisa e similares para executar tarefas agendadas em intervalos aproximadamente regulares

Veja: http://code.google.com/p/django-poormanscron/

user41767
fonte
2
Isso também pressupõe que seu aplicativo Django esteja acessível na Web, o que não seria o caso de implantações em LANs e VPNs.
TimH - Codidact
10

Eu tinha exatamente o mesmo requisito há um tempo atrás e acabei resolvendo-o usando o APScheduler ( Guia do Usuário )

Isso torna os trabalhos de agendamento super simples e o mantém independente da execução de algum código com base na solicitação. A seguir, é apresentado um exemplo simples.

from apscheduler.schedulers.background import BackgroundScheduler

scheduler = BackgroundScheduler()
job = None

def tick():
    print('One tick!')\

def start_job():
    global job
    job = scheduler.add_job(tick, 'interval', seconds=3600)
    try:
        scheduler.start()
    except:
        pass

Espero que isso ajude alguém!

PhoenixDev
fonte
9

A sugestão de Brian Neal de executar comandos de gerenciamento via cron funciona bem, mas se você estiver procurando por algo um pouco mais robusto (ainda não tão elaborado quanto o aipo), eu procuraria uma biblioteca como o Kronos :

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass
Johannes Gorset
fonte
9

RabbitMQ e Aipo têm mais recursos e recursos de manipulação de tarefas que o Cron. Se a falha da tarefa não for um problema e você acha que lidará com tarefas quebradas na próxima chamada, então o Cron é suficiente.

O Aipo e o AMQP permitirão que você lide com a tarefa quebrada e ela será executada novamente por outro trabalhador (os trabalhadores do aipo aguardam a próxima tarefa a ser trabalhada), até que o max_retriesatributo da tarefa seja atingido. Você pode até invocar tarefas em caso de falha, como registrar a falha ou enviar um email para o administrador assim que este max_retriesfor alcançado.

E você pode distribuir servidores Celery e AMQP quando precisar escalar seu aplicativo.

Ravi Kumar
fonte
8

Eu pessoalmente uso o cron, mas as partes do agendamento de tarefas do django-extensions parecem interessantes.

Van Gale
fonte
Ainda depende do cron para acionar, apenas adiciona outra camada de abstração no meio. Não tenho certeza se vale a pena, pessoalmente.
2411 Carl Meyer
Concordo e, depois de pensar nisso, não quero solicitar o middleware que diminui a velocidade do meu site (ala poormanscron acima) quando o cron puder fazer o trabalho melhor de qualquer maneira.
Van Gale
7

Embora não faça parte do Django, o Airflow é um projeto mais recente (a partir de 2016) que é útil para o gerenciamento de tarefas.

O Airflow é um sistema de automação e programação de fluxo de trabalho que pode ser usado para criar e gerenciar pipelines de dados. Uma interface do usuário baseada na Web fornece ao desenvolvedor uma variedade de opções para gerenciar e visualizar esses pipelines.

O fluxo de ar é escrito em Python e construído usando o Flask.

O Airflow foi criado por Maxime Beauchemin no Airbnb e de código aberto na primavera de 2015. Ingressou no programa de incubação da Apache Software Foundation no inverno de 2016. Aqui está a página do projeto Git e algumas informações adicionais .

Alexander
fonte
6

Coloque o seguinte na parte superior do seu arquivo cron.py:

#!/usr/bin/python
import os, sys
sys.path.append('/path/to/') # the parent directory of the project
sys.path.append('/path/to/project') # these lines only needed if not on path
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

# imports and code below
Matt McCormick
fonte
6

Eu apenas pensei sobre esta solução bastante simples:

  1. Defina uma função de exibição do_work (req, param) como faria com qualquer outra exibição, com mapeamento de URL, retorne um HttpResponse e assim por diante.
  2. Configurar uma tarefa cron com suas preferências de tempo (ou usando AT ou tarefas agendadas no Windows) que corre onda http: // localhost / o / mapeados / url param = valor .

Você pode adicionar parâmetros, mas apenas adicionando parâmetros ao URL.

Diga-me o que vocês pensam.

[Update] Agora estou usando o comando runjob do django-extensions em vez de curl.

Meu cron é mais ou menos assim:

@hourly python /path/to/project/manage.py runjobs hourly

... e assim por diante, diariamente, mensalmente, etc. Você também pode configurá-lo para executar um trabalho específico.

Acho mais manejável e mais limpo. Não requer mapeamento de um URL para uma visualização. Basta definir sua classe de trabalho e crontab e pronto.

Michael
fonte
1
o único problema que sinto é a adição desnecessária de carga ao aplicativo e largura de banda apenas para executar um trabalho em segundo plano que seria melhor iniciado "internamente" e independente do aplicativo veiculado. Mas, além disso, este é um django-cron inteligente e genérico, porque pode até ser invocado por agentes externos ao servidor do aplicativo!
Nemesisfixx
Você está certo, foi por isso que mudei para o uso de trabalhos de django-command-extensions. Veja minha atualização para minha resposta.
Michael
4

depois da parte do código, eu posso escrever qualquer coisa como o meu views.py :)

#######################################
import os,sys
sys.path.append('/home/administrator/development/store')
os.environ['DJANGO_SETTINGS_MODULE']='store.settings'
from django.core.management impor setup_environ
from store import settings
setup_environ(settings)
#######################################

de http://www.cotellese.net/2007/09/27/running-external-scripts-against-django-models/

xiaohei
fonte
3

Você deveria definitivamente conferir o django-q! Não requer configuração adicional e, possivelmente, possui tudo o necessário para lidar com qualquer problema de produção em projetos comerciais.

É ativamente desenvolvido e integra-se muito bem com django, django ORM, mongo, redis. Aqui está minha configuração:

# django-q
# -------------------------------------------------------------------------
# See: http://django-q.readthedocs.io/en/latest/configure.html
Q_CLUSTER = {
    # Match recommended settings from docs.
    'name': 'DjangoORM',
    'workers': 4,
    'queue_limit': 50,
    'bulk': 10,
    'orm': 'default',

# Custom Settings
# ---------------
# Limit the amount of successful tasks saved to Django.
'save_limit': 10000,

# See https://github.com/Koed00/django-q/issues/110.
'catch_up': False,

# Number of seconds a worker can spend on a task before it's terminated.
'timeout': 60 * 5,

# Number of seconds a broker will wait for a cluster to finish a task before presenting it again. This needs to be
# longer than `timeout`, otherwise the same task will be processed multiple times.
'retry': 60 * 6,

# Whether to force all async() calls to be run with sync=True (making them synchronous).
'sync': False,

# Redirect worker exceptions directly to Sentry error reporter.
'error_reporter': {
    'sentry': RAVEN_CONFIG,
},
}
saran3h
fonte
3

Django APScheduler para trabalhos de agendador. O Advanced Python Scheduler (APScheduler) é uma biblioteca Python que permite agendar seu código Python para ser executado posteriormente, apenas uma vez ou periodicamente. Você pode adicionar novos trabalhos ou remover trabalhos antigos quando desejar.

nota: sou o autor desta biblioteca

Instalar o APScheduler

pip install apscheduler

Exibir função de arquivo para chamar

nome do arquivo: scheduler_jobs.py

def FirstCronTest():
    print("")
    print("I am executed..!")

Configurando o planejador

faça o arquivo execute.py e adicione os códigos abaixo

from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()

Suas funções escritas Aqui, as funções do planejador são escritas em scheduler_jobs

import scheduler_jobs 

scheduler.add_job(scheduler_jobs.FirstCronTest, 'interval', seconds=10)
scheduler.start()

Vincular o arquivo para execução

Agora, adicione a linha abaixo na parte inferior do arquivo URL

import execute
Chandan Sharma
fonte
2

Eu tive algo parecido com o seu problema hoje.

Eu não queria que isso fosse tratado pelo servidor através do cron (e a maioria das bibliotecas eram apenas auxiliares do cron no final).

Então, eu criei um módulo de agendamento e o anexei ao init .

Não é a melhor abordagem, mas me ajuda a ter todo o código em um único local e com a execução relacionada ao aplicativo principal.

Fabricio Buzeto
fonte
2

Sim, o método acima é ótimo. E eu tentei alguns deles. Por fim, encontrei um método como este:

    from threading import Timer

    def sync():

        do something...

        sync_timer = Timer(self.interval, sync, ())
        sync_timer.start()

Assim como recursivo .

Ok, espero que este método possa atender às suas necessidades. :)

Ni Xiaoni
fonte
1
Parará se o seu 'algo' falhar; lembre-se de lidar com todas as exceções nele. Mesmo assim, o servidor da web pode acabar com seu encadeamento em algum momento, não?
Lutz Prechelt 14/11
2

Uma solução mais moderna (em comparação com o aipo) é o Django Q: https://django-q.readthedocs.io/en/latest/index.html

Possui ótima documentação e é fácil de grok. O suporte ao Windows está ausente, porque o Windows não suporta o processo de bifurcação. Mas funciona bem se você criar seu ambiente de desenvolvimento usando o Windows for Linux Subsystem.

devdrc
fonte
Parece que você pode ainda usá-lo em um modo de cluster único no Windows
Yushin Washio
1

Eu uso o aipo para criar minhas tarefas periódicas. Primeiro você precisa instalá-lo da seguinte maneira:

pip install django-celery

Não se esqueça de registrar django-celerysuas configurações e, em seguida, você pode fazer algo assim:

from celery import task
from celery.decorators import periodic_task
from celery.task.schedules import crontab
from celery.utils.log import get_task_logger
@periodic_task(run_every=crontab(minute="0", hour="23"))
def do_every_midnight():
 #your code
David Felipe Camargo Polo
fonte
2
Percebo que este conselho está desatualizado e você pode integrar o aipo diretamente. Veja pypi.python.org/pypi/django-celery para detalhes.
Peter Brittain
Os documentos de aipo dizem que essa foi uma alteração na v3.1. Eu ainda não tentei.
Peter Brittain
1

Não tenho certeza se isso será útil para qualquer pessoa, já que tive que fornecer outros usuários do sistema para agendar os trabalhos, sem dar a eles acesso ao servidor real (Windows) Agendador de tarefas, criei este aplicativo reutilizável.

Observe que os usuários têm acesso a uma pasta compartilhada no servidor, onde podem criar o arquivo de comando / tarefa / .bat necessário. Esta tarefa pode ser agendada usando este aplicativo.

O nome do aplicativo é Django_Windows_Scheduler

ScreenShot: insira a descrição da imagem aqui

just10minutes
fonte
0

Se você deseja algo mais confiável que o Celery , tente o TaskHawk, construído sobre o AWS SQS / SNS .

Consulte: http://taskhawk.readthedocs.io

Sriram
fonte
0

Para projetos dockerized simples, eu realmente não conseguia ver nenhuma resposta existente.

Então, eu escrevi uma solução muito básica, sem a necessidade de bibliotecas ou gatilhos externos, que são executados por conta própria. Nenhum os-cron externo necessário, deve funcionar em todos os ambientes.

Funciona adicionando um middleware: middleware.py

import threading

def should_run(name, seconds_interval):
    from application.models import CronJob
    from django.utils.timezone import now

    try:
        c = CronJob.objects.get(name=name)
    except CronJob.DoesNotExist:
        CronJob(name=name, last_ran=now()).save()
        return True

    if (now() - c.last_ran).total_seconds() >= seconds_interval:
        c.last_ran = now()
        c.save()
        return True

    return False


class CronTask:
    def __init__(self, name, seconds_interval, function):
        self.name = name
        self.seconds_interval = seconds_interval
        self.function = function


def cron_worker(*_):
    if not should_run("main", 60):
        return

    # customize this part:
    from application.models import Event
    tasks = [
        CronTask("events", 60 * 30, Event.clean_stale_objects),
        # ...
    ]

    for task in tasks:
        if should_run(task.name, task.seconds_interval):
            task.function()


def cron_middleware(get_response):

    def middleware(request):
        response = get_response(request)
        threading.Thread(target=cron_worker).start()
        return response

    return middleware

models/cron.py:

from django.db import models


class CronJob(models.Model):
    name = models.CharField(max_length=10, primary_key=True)
    last_ran = models.DateTimeField()

settings.py:

MIDDLEWARE = [
    ...
    'application.middleware.cron_middleware',
    ...
]
yspreen
fonte
0

A maneira mais simples é escrever um comando de shell customizado, ver Documentação do Django e executá-lo usando um cronjob no linux. No entanto, eu recomendo o uso de um corretor de mensagens como o RabbitMQ juntamente com o aipo. Talvez você possa dar uma olhada neste tutorial

Hamfri
fonte