Menyiapkan pekerjaan yang dijadwalkan?

519

Saya telah bekerja pada aplikasi web menggunakan Django, dan saya ingin tahu apakah ada cara untuk menjadwalkan pekerjaan untuk dijalankan secara berkala.

Pada dasarnya saya hanya ingin menjalankan melalui database dan membuat beberapa perhitungan / pembaruan secara otomatis, secara teratur, tetapi sepertinya saya tidak dapat menemukan dokumentasi untuk melakukan hal ini.

Adakah yang tahu cara mengatur ini?

Untuk memperjelas: Saya tahu saya dapat mengatur cronpekerjaan untuk melakukan ini, tapi saya ingin tahu apakah ada beberapa fitur di Django yang menyediakan fungsi ini. Saya ingin orang dapat menggunakan aplikasi ini sendiri tanpa harus melakukan banyak konfigurasi (sebaiknya nol).

Saya telah mempertimbangkan untuk memicu tindakan ini "surut" dengan hanya memeriksa apakah suatu pekerjaan seharusnya sudah dijalankan sejak terakhir kali permintaan dikirim ke situs, tetapi saya berharap untuk sesuatu yang sedikit lebih bersih.

TM.
sumber
1
Jika Anda adalah situs-kinerja tinggi dan sudah menggunakan RabbitMQ inilah trik untuk berkeliling cron: Menggunakan AMQP melakukan cron seperti penjadwalan
Van Gale
Jika saya mengerti benar, Anda perlu menjadwalkan beberapa tugas di Django. Hal terbaik yang saya temukan hari ini adalah yang ini: celery.github.com/celery/index.html
Ali Nikneshan
apa pendapatmu tentang ini? github.com/reavis/django-cron
Domenico Monaco
Centang telah dilakukan hanya untuk menghindari Anda semua pekerjaan ini. [Penafian] saya membangun centang.
Siscia
2
github.com/coleifer/huey Huey perlu disebutkan di sini. Sangat mudah untuk melakukan setup dengan Django.
Brandon Bertelsen

Jawaban:

363

Salah satu solusi yang saya gunakan adalah melakukan ini:

1) Buat perintah manajemen kustom , mis

python manage.py my_cool_command

2) Gunakan cron(di Linux) atau at(di Windows) untuk menjalankan perintah saya pada waktu yang diperlukan.

Ini adalah solusi sederhana yang tidak perlu menginstal tumpukan AMQP yang berat. Namun ada keuntungan bagus menggunakan sesuatu seperti Celery, yang disebutkan dalam jawaban lain. Secara khusus, dengan Seledri itu baik untuk tidak harus menyebarkan logika aplikasi Anda ke file crontab. Namun solusi cron bekerja cukup baik untuk aplikasi kecil hingga menengah dan di mana Anda tidak ingin banyak ketergantungan eksternal.

EDIT:

Di versi Windows yang lebih baru atperintahnya sudah tidak digunakan lagi untuk Windows 8, Server 2012 dan di atasnya. Anda dapat menggunakan schtasks.exeuntuk penggunaan yang sama.

**** PEMBARUAN **** Ini tautan baru django doc untuk menulis perintah manajemen kustom

Brian Neal
sumber
5
Apakah ini cara untuk melakukan ini tanpa layanan eksternal tetapi menggunakan proses kerangka Django hanya berjalan?
sergzach
4
Aplikasi @Brian_Neal django_cron.
sergzach
2
Tolong bantu saya memahami bagaimana saya menjalankan perintah manajemen di lingkungan virtual menggunakan cron pada hari terakhir setiap bulan.
mmrs151
2
@ergergach saya menindaklanjuti komentar ini dan ternyata ada dua paket dengan nama ini. The Django-cron di Google Code dan Django-cron di Github . Mereka sedikit berbeda tetapi keduanya menarik. Keduanya memungkinkan Anda untuk mendefinisikan crons dengan cara 'Djangonic'. Yang pertama sedikit lebih tua dan bertujuan untuk bekerja tanpa tugas eksternal (yaitu cron). Yang kedua di sisi lain mengharuskan Anda untuk mengatur cron untuk menjalankan python manage.py runcronsyang kemudian menjalankan semua crons yang telah Anda tetapkan dan terdaftar.
driftcatcher
1
@ergergach Saya berasumsi Anda merujuk yang pertama, "django-cron on Google Code". Anda benar tentang itu. Inilah sebenarnya mengapa saya memilih yang kedua, "django-cron on GitHub", karena itu membuat Anda memiliki pengaturan / manajemen crontab sederhana - hanya satu crontab, merujuk pada perintah manajemen - tetapi karena Anda menggunakan perintah terpisah proses cron Anda menghindari masalah sinkronisasi ini (sejauh yang saya tahu).
driftcatcher
152

Selery adalah antrian tugas terdistribusi, dibangun di atas AMQP (RabbitMQ). Itu juga menangani tugas-tugas berkala dengan cara yang mirip cron (lihat tugas-tugas berkala ). Tergantung pada aplikasi Anda, itu mungkin layak dilihat.

Seledri cukup mudah untuk diatur dengan Django ( dokumen ), dan tugas-tugas berkala benar-benar akan melewatkan tugas yang terlewat jika terjadi downtime. Selery juga memiliki mekanisme coba lagi bawaan, jika tugasnya gagal.

dln
sumber
51

Kami telah open-source yang saya pikir adalah aplikasi terstruktur. bahwa solusi Brian di atas juga menyinggung. Kami akan sangat menyukai setiap / semua umpan balik!

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

Itu datang dengan satu perintah manajemen:

./manage.py runcrons

Itu berhasil. Setiap cron dimodelkan sebagai kelas (jadi semuanya OO) dan masing-masing cron berjalan pada frekuensi yang berbeda dan kami memastikan jenis cron yang sama tidak berjalan secara paralel (seandainya crons sendiri membutuhkan waktu lebih lama untuk berjalan daripada frekuensinya!)

chachra
sumber
5
@ chachra Maaf, saya tahu ini mungkin pertanyaan yang bodoh, tetapi apakah ini akan bekerja pada windows melalui atatau itu dirancang khusus untuk bekerja dengan cron?
Bruno Finger
38

Jika Anda menggunakan OS POSIX standar, Anda menggunakan cron .

Jika Anda menggunakan Windows, Anda gunakan di .

Tulis perintah manajemen Django ke

  1. Cari tahu apa platform mereka.

  2. Baik jalankan perintah "AT" yang sesuai untuk pengguna Anda, atau perbarui crontab untuk pengguna Anda.

S.Lott
sumber
10
Saya ingin memilikinya digulung ke dalam aplikasi Django saya jika memungkinkan.
TM.
@TM: Apa maksudnya "digulung ke dalam aplikasi Django saya"? Tolong jelaskan pertanyaan Anda.
S.Lott
10
Saya ingin orang-orang dapat dengan mudah menyebarkan aplikasi ini tanpa harus mengatur pekerjaan cron sendiri.
TM.
1
Anda selalu dapat membungkus antarmuka cron ke dalam aplikasi Anda.
monkut
BSD, Mac, dan semua OS yang mirip Unix memiliki cron.
DylanYoung
23

Aplikasi Django pluggable baru yang menarik: Django-chronograph

Anda hanya perlu menambahkan satu entri cron yang bertindak sebagai penghitung waktu, dan Anda memiliki antarmuka admin Django yang sangat bagus ke dalam skrip untuk dijalankan.

Van Gale
sumber
2
django-chronograph tidak terawat. Garpu lebih baik: github.com/chrisspen/django-chroniker
Menda
16

Lihatlah Django Poor Man's Cron yang merupakan aplikasi Django yang menggunakan robot spam, robot pengindeksan mesin pencari dan juga untuk menjalankan tugas terjadwal dalam interval yang kurang lebih teratur

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

pengguna41767
sumber
2
Ini juga mengasumsikan bahwa aplikasi Django Anda dapat diakses dari web, yang tidak akan berlaku untuk penyebaran pada LAN dan VPN.
TimH - Codidact
10

Saya memiliki persyaratan yang persis sama beberapa waktu lalu, dan akhirnya menyelesaikannya menggunakan APScheduler ( Panduan Pengguna )

Itu membuat pekerjaan penjadwalan super sederhana, dan membuatnya independen untuk dari eksekusi berdasarkan permintaan beberapa kode. Berikut ini adalah contoh sederhana.

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

Semoga ini bisa membantu seseorang!

PhoenixDev
sumber
9

Saran Brian Neal untuk menjalankan perintah manajemen melalui cron bekerja dengan baik, tetapi jika Anda mencari sesuatu yang sedikit lebih kuat (namun tidak serumit Celery) saya akan melihat ke perpustakaan seperti Kronos :

# app/cron.py

import kronos

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

RabbitMQ dan Celery memiliki lebih banyak fitur dan kemampuan penanganan tugas daripada Cron. Jika kegagalan tugas tidak menjadi masalah, dan Anda pikir Anda akan menangani tugas yang rusak di panggilan berikutnya, maka Cron sudah cukup.

Seledri & AMQP akan membiarkan Anda menangani tugas yang rusak, dan itu akan dieksekusi lagi oleh pekerja lain (pekerja Seledri mendengarkan tugas berikutnya untuk dikerjakan), sampai max_retriesatribut tugas tercapai. Anda bahkan dapat menjalankan tugas pada kegagalan, seperti mencatat kegagalan, atau mengirim email ke admin setelah max_retriestercapai.

Dan Anda dapat mendistribusikan server Seledri dan AMQP ketika Anda perlu mengatur skala aplikasi Anda.

Ravi Kumar
sumber
8

Saya pribadi menggunakan cron, tetapi bagian Penjadwalan Pekerjaan dari Django-ekstensi terlihat menarik.

Van Gale
sumber
Masih tergantung pada cron untuk memicu, cukup tambahkan lapisan abstraksi lain di antaranya. Tidak yakin itu layak, secara pribadi.
Carl Meyer
Saya setuju, dan setelah memikirkannya saya tidak ingin meminta middleware memperlambat situs saya (ala poormanscron di atas) ketika cron dapat melakukan pekerjaan dengan lebih baik.
Van Gale
7

Meskipun bukan bagian dari Django, Airflow adalah proyek yang lebih baru (per 2016) yang berguna untuk manajemen tugas.

Airflow adalah sistem otomatisasi dan penjadwalan alur kerja yang dapat digunakan untuk membuat dan mengelola saluran data. UI berbasis web memberi pengembang sejumlah pilihan untuk mengelola dan melihat saluran pipa ini.

Aliran udara ditulis dengan Python dan dibangun menggunakan Flask.

Airflow dibuat oleh Maxime Beauchemin di Airbnb dan bersumber terbuka pada musim semi 2015. Airflow bergabung dengan program inkubasi Apache Software Foundation pada musim dingin 2016. Berikut adalah halaman proyek Git dan beberapa informasi latar belakang tambahan .

Alexander
sumber
6

Letakkan yang berikut di bagian atas file cron.py Anda:

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

Saya hanya memikirkan solusi yang agak sederhana ini:

  1. Tentukan fungsi tampilan do_work (req, param) seperti yang Anda lakukan dengan tampilan lain, dengan pemetaan URL, kembalikan respons HttpResponse dan sebagainya.
  2. Atur pekerjaan cron dengan preferensi waktu Anda (atau menggunakan AT atau Tugas Terjadwal di Windows) yang menjalankan curl http: // localhost / your / mapped / url? Param = value .

Anda dapat menambahkan parameter tetapi hanya menambahkan parameter ke URL.

Katakan apa yang kalian pikirkan.

[Perbarui] Saya sekarang menggunakan perintah runjob dari django-extensions bukan curl.

Cron saya terlihat seperti ini:

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

... dan seterusnya untuk harian, bulanan, dll. Anda juga dapat mengaturnya untuk menjalankan pekerjaan tertentu.

Saya merasa lebih mudah diatur dan lebih bersih. Tidak memerlukan pemetaan URL untuk dilihat. Cukup tentukan kelas pekerjaan Anda dan crontab dan Anda sudah siap.

Michael
sumber
1
Satu-satunya masalah yang saya rasakan adalah tidak perlu menambahkan beban ke aplikasi dan bandwidth hanya untuk menjalankan pekerjaan latar belakang yang lebih baik akan diluncurkan "secara internal" dan independen dari aplikasi yang melayani. Tapi selain itu, ini adalah pintar dan django-cron yang lebih umum karena bahkan dapat dipanggil oleh agen eksternal ke server aplikasi!
nemesisfixx
Anda benar, itu sebabnya saya pindah ke menggunakan pekerjaan dari Django-command-extensions. Lihat pembaruan saya untuk jawaban saya.
Michael
4

setelah bagian kode, saya bisa menulis apa saja seperti views.py saya :)

#######################################
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)
#######################################

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

Xiaohei
sumber
3

Anda pasti harus memeriksa Django-q! Ini tidak memerlukan konfigurasi tambahan dan sangat mungkin semua yang diperlukan untuk menangani masalah produksi pada proyek komersial.

Ini aktif dikembangkan dan terintegrasi dengan sangat baik dengan Django, Django ORM, Mongo, Redis. Ini konfigurasi saya:

# 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
sumber
3

Django APScheduler untuk Pekerjaan Penjadwal. Penjadwal Python Lanjutan (APScheduler) adalah pustaka Python yang memungkinkan Anda menjadwalkan kode Python Anda untuk dieksekusi nanti, baik hanya sekali atau secara berkala. Anda dapat menambahkan pekerjaan baru atau menghapus yang lama dengan cepat.

catatan: Saya penulis perpustakaan ini

Instal APScheduler

pip install apscheduler

Lihat fungsi file untuk memanggil

nama file: scheduler_jobs.py

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

Mengkonfigurasi penjadwal

buat file execut.py dan tambahkan kode di bawah ini

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

Fungsi tertulis Anda Di sini, fungsi scheduler ditulis dalam scheduler_jobs

import scheduler_jobs 

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

Tautkan File untuk Eksekusi

Sekarang, tambahkan baris di bawah ini di bagian bawah file Url

import execute
Chandan Sharma
sumber
2

Saya memiliki sesuatu yang mirip dengan masalah Anda hari ini.

Saya tidak ingin itu ditangani oleh server trhough cron (dan sebagian besar Lib hanya pembantu cron pada akhirnya).

Jadi saya telah membuat modul penjadwalan dan melampirkannya di init .

Ini bukan pendekatan terbaik, tetapi ini membantu saya untuk memiliki semua kode di satu tempat dan dengan eksekusi yang terkait dengan aplikasi utama.

Fabricio Buzeto
sumber
2

Ya, metode di atas sangat bagus. Dan saya mencoba beberapa dari mereka. Akhirnya, saya menemukan metode seperti ini:

    from threading import Timer

    def sync():

        do something...

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

Sama seperti Rekursif .

Ok, saya harap metode ini dapat memenuhi kebutuhan Anda. :)

Ni Xiaoni
sumber
1
Akan berhenti jika 'sesuatu' Anda gagal, jadi pastikan Anda menangani semua pengecualian di dalamnya. Bahkan kemudian, server web mungkin membunuh utas Anda di beberapa titik, bukan?
Lutz Prechelt
2

Solusi yang lebih modern (dibandingkan dengan Seledri) adalah Django Q: https://django-q.readthedocs.io/en/latest/index.html

Ini memiliki dokumentasi yang bagus dan mudah untuk grok. Dukungan Windows kurang, karena Windows tidak mendukung proses forking. Tapi itu berfungsi dengan baik jika Anda membuat lingkungan dev Anda menggunakan Subsistem Windows untuk Linux.

devdrc
sumber
Tampaknya Anda masih dapat menggunakannya dalam mode satu-kluster di Windows
Yushin Washio
1

Saya menggunakan seledri untuk membuat tugas berkala saya. Pertama, Anda perlu menginstalnya sebagai berikut:

pip install django-celery

Jangan lupa untuk mendaftar django-celerydi pengaturan Anda dan kemudian Anda dapat melakukan sesuatu seperti ini:

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
sumber
2
Saya perhatikan bahwa saran ini sudah ketinggalan zaman dan Anda dapat mengintegrasikan seledri secara langsung. Lihat pypi.python.org/pypi/django-celery untuk detailnya.
Peter Brittain
Dokumen seledri mengatakan bahwa ini adalah perubahan dalam v3.1. Saya belum mencobanya sendiri.
Peter Brittain
1

Saya tidak yakin apakah ini akan berguna bagi siapa pun, karena saya harus menyediakan pengguna lain dari sistem untuk menjadwalkan pekerjaan, tanpa memberi mereka akses ke Penjadwal Tugas server (windows), saya membuat aplikasi yang dapat digunakan kembali ini.

Harap perhatikan pengguna memiliki akses ke satu folder bersama di server tempat mereka dapat membuat file perintah / tugas / .bat yang diperlukan. Tugas ini kemudian dapat dijadwalkan menggunakan aplikasi ini.

Nama aplikasi adalah Django_Windows_Scheduler

Tangkapan Layar: masukkan deskripsi gambar di sini

hanya 10 menit
sumber
0

Jika Anda menginginkan sesuatu yang lebih dapat diandalkan daripada Seledri , coba TaskHawk yang dibangun di atas AWS SQS / SNS .

Rujuk: http://taskhawk.readthedocs.io

Sriram
sumber
0

Untuk proyek-proyek buruh pelabuhan sederhana, saya tidak bisa benar-benar melihat jawaban yang sesuai.

Jadi saya menulis solusi yang sangat barebones tanpa perlu perpustakaan atau pemicu eksternal, yang berjalan sendiri. Tidak diperlukan os-cron eksternal, harus bekerja di setiap lingkungan.

Ini berfungsi dengan menambahkan 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
sumber
0

Cara sederhana adalah dengan menulis perintah shell kustom lihat Django Documentation dan jalankan dengan menggunakan cronjob di linux. Namun saya sangat merekomendasikan menggunakan broker pesan seperti RabbitMQ ditambah dengan seledri. Mungkin Anda bisa melihat Tutorial ini

Hamfri
sumber