Zamanlanmış bir iş mi ayarladınız?


519

Django kullanarak bir web uygulaması üzerinde çalışıyorum ve periyodik olarak çalışacak bir iş planlamanın bir yolu olup olmadığını merak ediyorum.

Temelde sadece veritabanı üzerinden çalıştırmak ve otomatik, düzenli olarak bazı hesaplamalar / güncellemeler yapmak istiyorum, ama bunu yaparken herhangi bir belge bulamıyorum görünmüyor.

Bunu nasıl ayarlayacağını bilen var mı?

Açıklığa kavuşturmak için: Bunu cronyapmak için bir iş kurabileceğimi biliyorum , ancak Django'da bu işlevi sağlayan bazı özellikler olup olmadığını merak ediyorum. İnsanların çok fazla yapılandırma (tercihen sıfır) yapmadan bu uygulamayı kendileri dağıtabilmelerini istiyorum.

Bir siteye son istek gönderildikten sonra bir işin yürütülüp yürütülmediğini kontrol ederek bu işlemleri "geriye dönük olarak" tetiklemeyi düşündüm, ancak biraz daha temiz bir şey umuyorum.


1
Yüksek performanslı bir siteyseniz ve zaten RabbitMQ kullanıyorsanız, cron'u dolaşmak için bir püf noktası: Kron benzeri zamanlama yapmak
Van Gale

Doğru anlarsam, Django'da bazı görevler zamanlamanız gerekir. Bu günlerde bulduğum en iyi şey şu: celery.github.com/celery/index.html
Ali Nikneshan

bunun hakkında ne düşünüyorsun? github.com/reavis/django-cron
Domenico Monaco

Bütün bu çalışmalardan kaçınmak için kene olsa. [Feragat] Kene inşa ediyorum.
Mart'ta Siscia

2
github.com/coleifer/huey Huey'nin burada bir söze ihtiyacı var. Django ile kurulumu gülünç derecede kolaydır.
Brandon Bertelsen

Yanıtlar:


363

Çalıştığım bir çözüm bunu yapmaktır:

1) Özel bir yönetim komutu oluşturun , örn.

python manage.py my_cool_command

2) Komutumu gerekli zamanlarda çalıştırmak için ( cronLinux'ta) veya at(Windows'ta) kullanın.

Bu, ağır bir AMQP yığını yüklemeyi gerektirmeyen basit bir çözümdür. Bununla birlikte, diğer cevaplarda bahsedilen Kereviz gibi bir şey kullanmanın güzel avantajları vardır. Özellikle Kereviz ile uygulama mantığınızı crontab dosyalarına yaymak zorunda değilsiniz. Bununla birlikte, cron çözümü, küçük ve orta ölçekli uygulamalar için ve çok fazla dış bağımlılık istemediğinizde oldukça iyi çalışır.

DÜZENLE:

Windows'un sonraki sürümlerinde, atkomut Windows 8, Server 2012 ve sonraki sürümler için kullanımdan kaldırılmıştır. Sen kullanabilirsiniz schtasks.exeaynı kullanım için.

**** GÜNCELLEME **** Bu özel yönetim komutu yazmak için django doc yeni bağlantı


5
Bu, harici hizmetler olmadan, yalnızca çalışan bir django çerçeve işlemi kullanarak bunu yapmanın bir yolu mu?
sergzach

4
@Brian_Neal django_cron uygulaması.
sergzach

2
Lütfen her ayın son gününde cron kullanarak sanal bir ortamda nasıl yönetim komutu çalıştıracağımı anlamama yardımcı olun.
mmrs151

2
@sergzach Bu yorumu takip ettim ve bu isimde iki paket olduğu ortaya çıktı. Google Code django-cron ve Github django-cron . Biraz farklı ama ikisi de ilginç. Her ikisi de kronları 'Djangonic' bir şekilde tanımlamanızı sağlar. Birincisi biraz daha eskidir ve harici bir görev (yani cron) olmadan çalışmayı amaçlamaktadır. İkincisi ise, python manage.py runcronsdaha sonra tanımladığınız ve kaydettiğiniz tüm crons'ları çalıştıran bir cron ayarlamanızı gerektirir .
driftcatcher

1
@sergzach İlki "Google Kod üzerinde django-cron" dan bahsettiğinizi varsayıyorum. Bu konuda haklısın. Aslında bu yüzden ikincisini tercih ettim, "GitHub'da django-cron", çünkü bunu basit bir crontab kurulumuna / yönetimine sahip olursunuz - yönetim komutuna atıfta bulunan tek bir crontab - ama ayrı bir kullandığınız için cron işlemi bu senkronizasyon sorunu (anlayabildiğim kadarıyla) kaçının.
driftcatcher

152

Kereviz , AMQP (RabbitMQ) üzerine kurulmuş dağıtılmış bir görev kuyruğudur. Ayrıca periyodik görevleri kron benzeri bir şekilde işler (bkz. Periyodik görevler ). Uygulamanıza bağlı olarak, bir gander değerinde olabilir.

Kereviz django ( dokümanlar ) ile kurmak oldukça kolaydır ve periyodik görevler kesinti durumunda kaçırılan görevleri atlar. Kereviz ayrıca bir görev başarısız olursa yerleşik yeniden deneme mekanizmalarına sahiptir.


51

Yapısal bir uygulama olduğunu düşündüğüm şeyi açık kaynaklı hale getirdik. Brian'ın yukarıdaki çözümü de ima ediyor. Herhangi bir geri bildirim isteriz!

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

Bir yönetim komutu ile birlikte gelir:

./manage.py runcrons

Bu işi yapar. Her cron bir sınıf olarak modellenir (böylece tüm OO'ları) ve her cron farklı bir frekansta çalışır ve aynı cron tipinin paralel çalışmadığından emin oluruz (eğer kronların frekanslarından daha uzun süre çalışması durumunda!)


5
@chachra Üzgünüm, bunun aptalca bir soru olabileceğini biliyorum, ama bu pencereler üzerinde atçalışacak cronmı yoksa özel olarak çalışmak için mi tasarlanmıştı ?
Bruno Finger

38

Standart bir POSIX işletim sistemi kullanıyorsanız, cron kullanırsınız .

Eğer Windows kullanıyorsanız, kullandığınız en .

Adresine bir Django yönetim komutu yazma

  1. Hangi platformda olduklarını öğrenin.

  2. Kullanıcılarınız için uygun "AT" komutunu çalıştırın veya kullanıcılarınız için crontab'ı güncelleyin.


10
Mümkünse django uygulamamın içine yerleştirilmesini istiyorum.
TM.

@TM: "Django uygulamama aktarıldım" ne anlama geliyor? Lütfen sorunuzu netleştirin.
S.Lott

10
İnsanların kendi kendilerine cron işleri kurmak zorunda kalmadan bu uygulamayı kolayca dağıtabilmelerini istiyorum.
TM.

1
Her zaman cron arayüzünü uygulamanıza sarabilirsiniz.
monkut

BSD, Mac ve herhangi bir Unix benzeri işletim sistemi cron'a sahiptir.
DylanYoung

23

İlginç yeni takılabilir Django uygulaması: django-chronograph

Sadece bir zamanlayıcı görevi gören bir cron girişi eklemeniz gerekir ve çalıştırılacak komut dosyalarına çok güzel bir Django yönetici arayüzü vardır.


2
django-kronograf korunmamıştır. Çatal çok daha iyi gidiyor
Menda

16

Spambot, arama motoru indeksleme robotları ve benzer görevleri yaklaşık düzenli aralıklarla çalıştırmak için kullanılan bir Django uygulaması olan Django Poor Man's Cron'a bakın

Bkz. Http://code.google.com/p/django-poormanscron/


2
Bu ayrıca Django uygulamanızın web'den erişilebilir olduğunu varsayar; bu, LAN'larda ve VPN'lerde dağıtımlar için geçerli olmaz.
TimH - Codidact

10

Bir süre önce tam olarak aynı gereksinime sahiptim ve APScheduler kullanarak çözdüm ( Kullanıcı Kılavuzu )

Zamanlama işlerini süper basitleştirir ve bazı kodların istek tabanlı yürütülmesinden bağımsız tutar. Aşağıda basit bir örnek verilmiştir.

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

Umarım bu birine yardımcı olur!


9

Brian Neal'ın cron üzerinden yönetim komutları çalıştırma önerisi iyi çalışıyor, ancak biraz daha sağlam bir şey arıyorsanız (ancak Kereviz kadar ayrıntılı değil) Kronos gibi bir kütüphaneye bakardım :

# app/cron.py

import kronos

@kronos.register('0 * * * *')
def task():
    pass

9

RabbitMQ ve Kereviz, Cron'dan daha fazla özelliğe ve görev işleme özelliğine sahiptir. Görev hatası bir sorun değilse ve bir sonraki çağrıda bozuk görevleri ele alacağınızı düşünüyorsanız, Cron yeterlidir.

Kereviz ve AMQP , kırık görevi yerine getirmenize izin verir ve görev max_retriesözniteliğine ulaşılana kadar başka bir işçi (Kereviz çalışanları üzerinde çalışacak bir sonraki görevi dinler) tarafından tekrar yürütülür . Hatayı günlüğe kaydetme veya max_retriesulaşıldıktan sonra yöneticiye bir e-posta gönderme gibi başarısızlıkla ilgili görevleri bile çağırabilirsiniz .

Uygulamanızı ölçeklendirmeniz gerektiğinde Kereviz ve AMQP sunucularını dağıtabilirsiniz.


8

Şahsen cron kullanıyorum, ancak django uzantılarının İş Planlaması bölümleri ilginç görünüyor.


Hala tetikleme için cron'a bağlı, araya başka bir soyutlama katmanı ekliyor. Buna değdiğinden emin değilim.
Carl Meyer

Kabul ediyorum ve bu konuda düşündükten sonra cron zaten işi daha iyi yapabilir zaman sitemizi yavaşlatmak istemiyorum (yukarıdaki ala poormanscron).
Van Gale

7

Django'nun bir parçası olmasa da, Airflow görev yönetimi için yararlı olan daha yeni bir projedir (2016 itibariyle).

Airflow, veri boru hatlarını yazmak ve yönetmek için kullanılabilen bir iş akışı otomasyonu ve zamanlama sistemidir. Web tabanlı bir kullanıcı arayüzü, geliştiriciye bu boru hatlarını yönetmek ve görüntülemek için bir dizi seçenek sunar.

Hava akışı Python ile yazılmıştır ve Flask kullanılarak oluşturulmuştur.

Airflow, Airbnb'de Maxime Beauchemin tarafından yaratıldı ve 2015 ilkbaharında açık kaynaklıydı. 2016 kışında Apache Software Foundation'ın kuluçka programına katıldı. İşte Git proje sayfası ve bazı ek arka plan bilgileri .


6

Aşağıdakileri cron.py dosyanızın üstüne yerleştirin:

#!/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

6

Sadece bu oldukça basit çözümü düşündüm:

  1. URL eşlemesi ile diğer görünümlerde olduğu gibi do_work (req, param) gibi bir görünüm işlevi tanımlayın , bir HttpResponse vb. Döndürün .
  2. İshal zamanlama tercihleri ile bir cron işi kurma (Windows veya AT kullanırken veya zamanlanmış görevler) bukle http: // localhost / senin / eşleştirilmiş / url param = değer .

Parametreler ekleyebilirsiniz, ancak yalnızca URL'ye parametreler ekleyebilirsiniz.

Bana ne düşündüğünü söyle.

[Güncelleme] Şimdi curl yerine django uzantılarından runjob komutu kullanıyorum .

Benim cron böyle bir şey görünüyor:

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

... günlük, aylık vb. Belirli bir işi çalıştırmak için de ayarlayabilirsiniz.

Daha yönetilebilir ve daha temiz buluyorum. Bir URL'nin bir görünümle eşlenmesini gerektirmez. Sadece iş sınıfınızı ve crontab'ınızı tanımlayın ve hazırsınız.


1
Algılama tek sorun, zorunlu olarak app ve bant genişliği sadece "dahili" ve hizmet app bağımsız olarak daha iyi başlatılacak bir arka plan iş çalıştırmak için yük eklemek. Ancak bunun dışında, bu akıllıca ve daha genel bir django-cron çünkü uygulamanın sunucusunun dışındaki ajanlar tarafından bile çağrılabilir!
nemesisfixx

Haklısın, bu yüzden django-komut uzantılarından işleri kullanmaya başladım. Cevabımla ilgili güncellememe bakın.
Michael


3

Kesinlikle django-q kontrol etmelisiniz! Ek yapılandırma gerektirmez ve ticari projelerde üretim sorunlarını ele almak için gereken her şeye sahiptir.

Aktif olarak geliştirildi ve django, django ORM, mongo, redis ile çok iyi entegre oluyor. İşte benim yapılandırmam:

# 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,
},
}

3

Zamanlayıcı İşler için Django APScheduler. Gelişmiş Python Zamanlayıcı (APScheduler), Python kodunuzu daha sonra yalnızca bir kez veya periyodik olarak yürütülecek şekilde planlamanızı sağlayan bir Python kütüphanesidir. İstediğiniz gibi yeni işler ekleyebilir veya eskilerini anında kaldırabilirsiniz.

not: ben bu kütüphanenin yazarıyım

APScheduler'ı yükleyin

pip install apscheduler

Aranacak dosya işlevini görüntüle

dosya adı: scheduler_jobs.py

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

Zamanlayıcıyı yapılandırma

execute.py dosyasını oluşturun ve aşağıdaki kodları ekleyin

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

Yazılı işlevleriniz Burada, zamanlayıcı işlevleri scheduler_jobs içinde yazılır

import scheduler_jobs 

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

Yürütme Dosyasını Bağlayın

Şimdi, URL dosyasının altına aşağıdaki satırı ekleyin

import execute

2

Bugün senin sorununla benzer bir şey yaşadım.

Ben sunucu trron cron tarafından ele almak istemiyordu (ve libs çoğu sadece cron yardımcıları sonunda).

Bu yüzden bir zamanlama modülü oluşturdum ve init'e ekledim .

En iyi yaklaşım değil, ancak tüm kodu tek bir yerde ve ana uygulama ile ilgili yürütülmesi ile bana yardımcı olur.


2

Evet, yukarıdaki yöntem çok harika. Bazılarını denedim. Sonunda, böyle bir yöntem buldum:

    from threading import Timer

    def sync():

        do something...

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

Tıpkı Özyinelemeli gibi .

Tamam, umarım bu yöntem ihtiyacınızı karşılayabilir. :)


1
'Bir şey' hiç başarısız olursa duracaktır, bu yüzden içindeki tüm istisnaları ele aldığınızdan emin olun. O zaman bile, web sunucusu iş parçacığınızı bir noktada öldürebilir, değil mi?
Lutz Prechelt


1

Periyodik görevlerimi oluşturmak için kereviz kullanıyorum. İlk önce aşağıdaki gibi yüklemeniz gerekir:

pip install django-celery

django-celeryAyarlarınıza kaydolmayı unutmayın ve sonra böyle bir şey yapabilirsiniz:

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

2
Bu tavsiyenin güncel olmadığını ve kerevizi doğrudan entegre edebileceğinizi fark ettim. Ayrıntılar için bkz. Pypi.python.org/pypi/django-celery .
Peter Brittain

Kereviz dokümanları bunun v3.1'de bir değişiklik olduğunu söylüyor. Henüz kendim denemedim.
Peter Brittain

1

Sistemin diğer kullanıcılarına gerçek sunucuya (windows) Görev Zamanlayıcı'ya erişim vermeden işleri zamanlamaları için sağlamak zorunda olduğumdan, bunun herkes için yararlı olacağından emin değilim, bu yeniden kullanılabilir uygulamayı oluşturdum.

Kullanıcıların, sunucuda gerekli komut / görev / .bat dosyasını oluşturabilecekleri bir paylaşılan klasöre erişebileceğini lütfen unutmayın. Bu görev daha sonra bu uygulama kullanılarak zamanlanabilir.

Uygulama adı (şimdiki değeri) Django_Windows_Scheduler

ScreenShot: resim açıklamasını buraya girin



0

Basit liman işleri için mevcut cevapların hiçbirini gerçekten göremedim.

Bu yüzden, kendi kendine çalışan harici kütüphanelere veya tetikleyicilere ihtiyaç duymadan çok barebone çözümü yazdım. Harici os-cron gerekmez, her ortamda çalışmalıdır.

Bir ara katman yazılımı ekleyerek çalışır: 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',
    ...
]

0

Basit bir yol özel bir kabuk komutu yazmak için bkz. Django Belgeleri ve linux üzerinde bir cronjob kullanarak yürütmek. Ancak çok kereviz ile birleştiğinde RabbitMQ gibi bir mesaj komisyoncusu kullanmanızı tavsiye ediyoruz. Belki bu Eğiticiye bir göz atabilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.