Thiết lập một công việc theo lịch trình?


519

Tôi đã làm việc trên một ứng dụng web bằng Django và tôi tò mò liệu có cách nào để sắp xếp công việc để chạy định kỳ không.

Về cơ bản tôi chỉ muốn chạy qua cơ sở dữ liệu và thực hiện một số tính toán / cập nhật một cách tự động, thường xuyên, nhưng dường như tôi không thể tìm thấy bất kỳ tài liệu nào về việc này.

Có ai biết làm thế nào để thiết lập này?

Để làm rõ: Tôi biết tôi có thể thiết lập một croncông việc để làm việc này, nhưng tôi tò mò liệu có một tính năng nào trong Django cung cấp chức năng này không. Tôi muốn mọi người có thể tự triển khai ứng dụng này mà không cần phải thực hiện nhiều cấu hình (tốt nhất là bằng không).

Tôi đã xem xét việc kích hoạt các hành động này "hồi tố" bằng cách kiểm tra xem một công việc có nên được thực hiện kể từ lần cuối cùng một yêu cầu được gửi đến trang web hay không, nhưng tôi hy vọng sẽ có thứ gì đó sạch sẽ hơn một chút.


1
Nếu bạn là một trang web hiệu suất cao và đã sử dụng RabbitMQ thì đây là một mẹo để khám phá cron: Sử dụng AMQP để thực hiện lập lịch giống như cron
Van Gale

Nếu tôi hiểu đúng, bạn cần lên lịch một số nhiệm vụ trong Django. Điều tốt nhất tôi tìm thấy những ngày này là cái này: celery.github.com/celery/index.html
Ali Nikneshan

Bạn nghĩ gì về điều này? github.com/reavis/django-cron
Domenico Monaco

Tick là mặc dù chỉ để tránh bạn tất cả công việc này. [Khước từ] Tôi xây dựng đánh dấu.
Siscia

2
github.com/coleifer/huey Huey cần đề cập ở đây. Thật dễ dàng để thiết lập với Django.
Brandon Bertelsen

Câu trả lời:


363

Một giải pháp mà tôi đã sử dụng là làm điều này:

1) Tạo lệnh quản lý tùy chỉnh , ví dụ:

python manage.py my_cool_command

2) Sử dụng cron(trên Linux) hoặc at(trên Windows) để chạy lệnh của tôi vào những thời điểm cần thiết.

Đây là một giải pháp đơn giản không yêu cầu cài đặt ngăn xếp AMQP nặng. Tuy nhiên, có những lợi thế tốt khi sử dụng một cái gì đó như Celery, được đề cập trong các câu trả lời khác. Đặc biệt, với Celery, thật tuyệt khi không phải truyền bá logic ứng dụng của bạn ra các tệp crontab. Tuy nhiên, giải pháp cron hoạt động khá độc đáo cho một ứng dụng có quy mô vừa và nhỏ và bạn không muốn có nhiều phụ thuộc bên ngoài.

BIÊN TẬP:

Trong phiên bản sau của windows, atlệnh không được dùng cho Windows 8, Server 2012 trở lên. Bạn có thể sử dụng schtasks.execho cùng sử dụng.

**** CẬP NHẬT **** Đây là liên kết mới của django doc để viết lệnh quản lý tùy chỉnh


5
Đây có phải là một cách để làm điều này mà không cần các dịch vụ bên ngoài nhưng chỉ sử dụng một quy trình khung django đang chạy?
sergzach

4
@Brian_Neal ứng dụng django_cron.
sergzach

2
Vui lòng giúp tôi hiểu cách tôi sẽ chạy lệnh quản lý trong môi trường ảo bằng cron vào ngày cuối cùng hàng tháng.
mmrs151

2
@sergzach Tôi theo dõi bình luận này và hóa ra có hai gói có tên này. Các django-cron trên Google Codedjango-cron trên Github . Họ hơi khác nhau nhưng cả hai thú vị. Cả hai đều cho phép bạn xác định các con quỷ theo cách 'Djangonic'. Cái đầu tiên là một chút cũ hơn và nhằm mục đích làm việc mà không có một nhiệm vụ bên ngoài (tức là cron). Mặt khác, cái thứ hai yêu cầu bạn thiết lập một cron để chạy python manage.py runcrons, sau đó chạy tất cả các crons bạn đã xác định và đăng ký.
driftcatcher

1
@sergzach Tôi giả sử bạn đang đề cập đến cái đầu tiên, "django-cron trên Google Code". Bạn nói đúng về điều đó. Đây thực sự là lý do tại sao tôi chọn cái thứ hai, "django-cron trên GitHub", bởi vì nó làm cho nó có một thiết lập / quản lý crontab đơn giản - chỉ một crontab, đề cập đến lệnh quản lý - nhưng vì bạn đang sử dụng một lệnh riêng quá trình cron bạn tránh vấn đề đồng bộ hóa này (theo như tôi có thể nói).
driftcatcher

152

Cần tây là một hàng đợi nhiệm vụ phân tán, được xây dựng trên AMQP (RabbitMQ). Nó cũng xử lý các nhiệm vụ định kỳ theo kiểu cron (xem các nhiệm vụ định kỳ ). Tùy thuộc vào ứng dụng của bạn, nó có thể đáng để ngông cuồng.

Cần tây khá dễ dàng để thiết lập với django ( tài liệu ) và các tác vụ định kỳ sẽ thực sự bỏ qua các tác vụ bị bỏ lỡ trong trường hợp ngừng hoạt động. Celery cũng có các cơ chế thử lại tích hợp, trong trường hợp một nhiệm vụ thất bại.


51

Chúng tôi đã mở nguồn những gì tôi nghĩ là một ứng dụng có cấu trúc. giải pháp của Brian trên ám chỉ quá. Chúng tôi sẽ yêu thích bất kỳ / tất cả thông tin phản hồi!

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

Nó đi kèm với một lệnh quản lý:

./manage.py runcrons

Đó là công việc. Mỗi cron được mô hình hóa thành một lớp (vì vậy tất cả OO của nó) và mỗi cron chạy ở một tần số khác nhau và chúng tôi đảm bảo cùng một loại cron không chạy song song (trong trường hợp các crons tự chạy lâu hơn tần số của chúng!)


5
@chachra Xin lỗi, tôi biết đây có thể là một câu hỏi ngớ ngẩn, nhưng nó sẽ hoạt động trên windows thông qua athay nó được thiết kế đặc biệt để làm việc với cron?
Bruno Finger

38

Nếu bạn đang sử dụng HĐH POSIX tiêu chuẩn, bạn sử dụng cron .

Nếu bạn đang sử dụng Windows, bạn sử dụng tại .

Viết lệnh quản lý Django để

  1. Tìm hiểu xem họ đang sử dụng nền tảng nào.

  2. Thực thi lệnh "AT" thích hợp cho người dùng của bạn hoặc cập nhật crontab cho người dùng của bạn.


10
Tôi muốn có nó cuộn lên trong ứng dụng django của tôi nếu có thể.
TM.

@TM: "Cuộn vào ứng dụng django của tôi" nghĩa là gì? Hãy làm rõ câu hỏi của bạn.
S.Lott

10
Tôi muốn mọi người có thể dễ dàng triển khai ứng dụng này mà không phải tự thiết lập công việc định kỳ.
TM.

1
Bạn luôn có thể bọc giao diện cron vào ứng dụng của bạn.
monkut

BSD, Mac và bất kỳ HĐH nào giống Unix đều có cron.
DylanYoung

23

Ứng dụng Django có thể cắm mới thú vị: django-chronograph

Bạn chỉ cần thêm một mục cron hoạt động như một bộ đếm thời gian và bạn có một giao diện quản trị Django rất đẹp vào các tập lệnh để chạy.


2
django-chronograph là không rõ ràng. Cái ngã ba đang hoạt động tốt hơn nhiều: github.com/chrisspen/django- synciker
Menda

16

Nhìn vào Cron của Django Poor Man, một ứng dụng Django sử dụng spam, robot lập chỉ mục công cụ tìm kiếm và tương tự để chạy các tác vụ theo lịch trình trong khoảng thời gian đều đặn

Xem: http://code.google.com.vn/p/django-poormanscron/


2
Điều này cũng giả định rằng ứng dụng Django của bạn có thể truy cập được từ web, điều này sẽ không xảy ra đối với việc triển khai trên mạng LAN và VPN.
TimH - Codidact

10

Tôi đã có chính xác yêu cầu tương tự trước đây và cuối cùng đã giải quyết nó bằng APScheduler ( Hướng dẫn sử dụng )

Nó làm cho việc lập lịch trình trở nên cực kỳ đơn giản và giữ cho nó độc lập với việc thực thi một số mã dựa trên yêu cầu. Sau đây là một ví dụ đơn giản.

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

Hy vọng điều này sẽ giúp ai đó!


9

Đề xuất của Brian Neal về việc chạy các lệnh quản lý thông qua cron hoạt động tốt, nhưng nếu bạn đang tìm kiếm thứ gì đó mạnh mẽ hơn một chút (nhưng không phức tạp như Celery), tôi sẽ tìm đến một thư viện như Kronos :

# app/cron.py

import kronos

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

9

RabbitMQ và Celery có nhiều tính năng và khả năng xử lý tác vụ hơn Cron. Nếu thất bại trong nhiệm vụ không phải là vấn đề và bạn nghĩ rằng bạn sẽ xử lý các tác vụ bị hỏng trong cuộc gọi tiếp theo, thì Cron là đủ.

Celery & AMQP sẽ cho phép bạn xử lý tác vụ bị hỏng và nó sẽ được thực thi lại bởi một công nhân khác (công nhân Celery lắng nghe nhiệm vụ tiếp theo để làm việc), cho đến khi max_retriesđạt được thuộc tính của nhiệm vụ . Bạn thậm chí có thể gọi các nhiệm vụ khi thất bại, như đăng nhập thất bại hoặc gửi email đến quản trị viên sau khi max_retriesđã đạt được.

Và bạn có thể phân phối máy chủ Celery và AMQP khi bạn cần mở rộng quy mô ứng dụng của mình.


8

Cá nhân tôi sử dụng cron, nhưng các phần Lập lịch công việc của phần mở rộng django trông thú vị.


Vẫn phụ thuộc vào cron để kích hoạt, chỉ cần thêm một lớp trừu tượng ở giữa. Không chắc chắn rằng nó có giá trị nó, cá nhân.
Carl Meyer

Tôi đồng ý và sau khi suy nghĩ về nó, tôi không muốn yêu cầu phần mềm trung gian làm chậm trang web của mình (ala poormanscron ở trên) khi cron có thể thực hiện công việc tốt hơn.
Van Gale

7

Mặc dù không phải là một phần của Django, Airflow là một dự án gần đây hơn (tính đến năm 2016) rất hữu ích cho việc quản lý tác vụ.

Airflow là một hệ thống lập lịch trình và tự động hóa công việc có thể được sử dụng để tác giả và quản lý các đường ống dữ liệu. Giao diện người dùng dựa trên web cung cấp cho nhà phát triển một loạt các tùy chọn để quản lý và xem các đường ống này.

Luồng khí được viết bằng Python và được xây dựng bằng Flask.

Airflow được Maxime Beauchemin tạo ra tại Airbnb và mở nguồn vào mùa xuân năm 2015. Nó đã tham gia chương trình ươm tạo của Quỹ Phần mềm Apache vào mùa đông năm 2016. Đây là trang dự án Git và một số thông tin cơ bản bổ sung .


6

Đặt phần sau vào đầu tệp cron.py của bạn:

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

Tôi chỉ nghĩ về giải pháp khá đơn giản này:

  1. Xác định chức năng xem do_work (req, param) như bạn làm với bất kỳ chế độ xem nào khác, với ánh xạ URL, trả về một HTTPResponse, v.v.
  2. Thiết lập một công việc định kỳ với các tùy chọn thời gian của bạn (hoặc sử dụng AT hoặc Tác vụ theo lịch trong Windows) chạy curl http: // localhost / your / mapped / url? Param = value .

Bạn có thể thêm tham số nhưng chỉ cần thêm tham số vào URL.

Nói cho tôi biết các bạn đang nghĩ gì.

[Cập nhật] Tôi hiện đang sử dụng lệnh runjob từ phần mở rộng django thay vì curl.

Cron của tôi trông giống như thế này:

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

... và cứ thế hàng ngày, hàng tháng, v.v. Bạn cũng có thể thiết lập nó để chạy một công việc cụ thể.

Tôi thấy nó dễ quản lý hơn và sạch hơn. Không yêu cầu ánh xạ URL tới chế độ xem. Chỉ cần xác định lớp công việc của bạn và crontab và bạn đã thiết lập.


1
chỉ có vấn đề về cảm biến là không nhất thiết phải thêm tải vào ứng dụng và băng thông chỉ để chạy một công việc nền sẽ được khởi chạy "nội bộ" và độc lập với ứng dụng phục vụ. Nhưng khác với điều này, đây là một django-cron thông minh hơn vì nó thậm chí có thể được gọi bởi các tác nhân bên ngoài máy chủ của ứng dụng!
nemeisfixx

Bạn nói đúng, đó là lý do tại sao tôi chuyển sang sử dụng các công việc từ phần mở rộng lệnh django. Xem cập nhật của tôi để trả lời của tôi.
Michael

4

sau phần mã, tôi có thể viết bất cứ thứ gì giống như lượt xem của mình :)

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

từ http://www.cotellese.net/2007/09/27/rucky-external-scripts-against-django-models/


3

Bạn chắc chắn nên kiểm tra django-q! Nó không yêu cầu cấu hình bổ sung và có khả năng mọi thứ cần thiết để xử lý bất kỳ vấn đề sản xuất nào trong các dự án thương mại.

Nó tích cực phát triển và tích hợp rất tốt với django, django ORM, mongo, redis. Đây là cấu hình của tôi:

# 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

Django APScheduler cho Công việc Lập lịch. Bộ lập lịch Python nâng cao (APScheduler) là một thư viện Python cho phép bạn lên lịch mã Python của mình để được thực thi sau, chỉ một lần hoặc theo định kỳ. Bạn có thể thêm các công việc mới hoặc loại bỏ những công việc cũ một cách nhanh chóng nếu bạn muốn.

lưu ý: Tôi là tác giả của thư viện này

Cài đặt APScheduler

pip install apscheduler

Xem chức năng tập tin để gọi

tên tệp: calendaruler_jobs.py

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

Cấu hình bộ lập lịch

tạo tập tin exec.txt và thêm các mã dưới đây

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

Các hàm viết của bạn Ở đây, các hàm lập lịch được viết bằng calendaruler_jobs

import scheduler_jobs 

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

Liên kết tệp để thực thi

Bây giờ, thêm dòng dưới đây vào dưới cùng của tệp Url

import execute

2

Tôi đã có một cái gì đó tương tự với vấn đề của bạn ngày hôm nay.

Tôi không muốn nó được xử lý bởi cron máy chủ (và hầu hết các lib chỉ là người trợ giúp cuối cùng).

Vì vậy, tôi đã tạo ra một mô-đun lập lịch và gắn nó vào init .

Đây không phải là cách tiếp cận tốt nhất, nhưng nó giúp tôi có tất cả mã ở một nơi duy nhất và với việc thực thi liên quan đến ứng dụng chính.


2

Vâng, phương pháp trên là rất tốt. Và tôi đã thử một vài trong số chúng. Cuối cùng, tôi tìm thấy một phương pháp như thế này:

    from threading import Timer

    def sync():

        do something...

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

Cũng giống như đệ quy .

Ok, tôi hy vọng phương pháp này có thể đáp ứng yêu cầu của bạn. :)


1
Sẽ dừng lại nếu "cái gì đó" của bạn từng thất bại, vì vậy hãy đảm bảo bạn xử lý tất cả các ngoại lệ trong đó. Thậm chí sau đó, máy chủ web có thể giết chết chủ đề của bạn tại một số điểm, có thể không?
Lutz Prechelt

2

Một giải pháp hiện đại hơn (so với Celery) là Django Q: https://django-q.readthedocs.io/en/latest/index.html

Nó có tài liệu tuyệt vời và dễ dàng để tìm kiếm. Hỗ trợ Windows còn thiếu, vì Windows không hỗ trợ quá trình chuyển đổi. Nhưng nó hoạt động tốt nếu bạn tạo môi trường dev của mình bằng Hệ thống con Windows cho Linux.


Có vẻ như bạn vẫn có thể sử dụng nó trong chế độ một cụm trên Windows
Yushin Washio

1

Tôi sử dụng cần tây để tạo ra các nhiệm vụ định kỳ của mình. Đầu tiên bạn cần cài đặt nó như sau:

pip install django-celery

Đừng quên đăng ký django-celerytrong cài đặt của bạn và sau đó bạn có thể làm một cái gì đó như thế này:

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
Tôi nhận thấy rằng lời khuyên này đã hết hạn và bạn có thể tích hợp cần tây trực tiếp. Xem pypi.python.org/pypi/django-celery để biết chi tiết.
Peter Brittain

Các tài liệu cần tây nói rằng đây là một thay đổi trong phiên bản 3.1. Tôi chưa thử nó lần nào.
Peter Brittain

1

Tôi không chắc điều này sẽ hữu ích cho bất kỳ ai, vì tôi phải cung cấp cho người dùng khác của hệ thống để lên lịch công việc, mà không cho họ quyền truy cập vào Trình lập lịch tác vụ (máy chủ) thực tế, tôi đã tạo ứng dụng có thể sử dụng lại này.

Xin lưu ý người dùng có quyền truy cập vào một thư mục dùng chung trên máy chủ nơi họ có thể tạo tệp lệnh / task / .bat cần thiết. Nhiệm vụ này sau đó có thể được lên lịch sử dụng ứng dụng này.

Tên ứng dụng là Django_Windows_Scheduler

Ảnh chụp màn hình: nhập mô tả hình ảnh ở đây



0

Đối với các dự án được neo đơn giản, tôi thực sự không thể thấy bất kỳ câu trả lời nào phù hợp.

Vì vậy, tôi đã viết một giải pháp rất đơn giản mà không cần đến các thư viện hoặc trình kích hoạt bên ngoài, nó tự chạy. Không cần os-cron bên ngoài, nên hoạt động trong mọi môi trường.

Nó hoạt động bằng cách thêm một phần mềm trung gian: 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

Cách đơn giản là viết lệnh shell tùy chỉnh, xem Django Documentation và thực thi nó bằng cronjob trên linux. Tuy nhiên tôi rất khuyên bạn nên sử dụng một nhà môi giới tin nhắn như RabbitMQ cùng với cần tây. Có lẽ bạn có thể xem Hướng dẫn này

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.