django - настроить запланированное задание?

<p>я работал над веб-приложением с использованием django, и мне любопытно, есть ли способ запланировать периодическое выполнение задания. </p><p>по сути, я просто хочу пробежаться по базе данных и делать некоторые расчеты/обновления автоматически, на регулярной основе, но я не могу найти какую-либо документацию по этому вопросу.</p><p>кто-нибудь знает, как это настроить?</p><p>для пояснения: я знаю, что могу создать для этого задание <code>cron</code>, но мне любопытно, есть ли в django какая-то функция, обеспечивающая эту функцию. я бы хотел, чтобы люди могли сами развернуть это приложение, не выполняя много настроек (желательно нулевых).</p><p>я подумал о том, чтобы инициировать эти действия «задним числом», просто проверив, нужно ли было запускать задание с момента последней отправки запроса на сайт, но я надеюсь на что-то более чистое.</p>

<p>одно решение, которое я использовал, состоит в том, чтобы сделать это:</p><p>1) создайте <a href="http://docs.djangoproject.com/en/dev/howto/custom-management-commands/#howto-custom-management-commands">пользовательскую команду управления</a> , например. </p><pre><code>python manage.py my\_cool\_command </code></pre><p>2) используйте <code>cron</code> (в linux) или <code>at</code> (в windows), чтобы запустить мою команду в нужное время.</p><p>это простое решение, которое не требует установки тяжелого стека amqp. однако есть хорошие преимущества использования чего-то вроде сельдерея, упомянутые в других ответах. в частности, с celery хорошо, что нет необходимости распространять логику вашего приложения в файлы crontab. однако решение cron довольно хорошо работает для приложений малого и среднего размера, где вам не нужно много внешних зависимостей.</p><p>правка:</p><p>в более поздней версии windows команда <code>at</code> устарела для windows 8, server 2012 и выше. вы можете использовать <code>schtasks.exe</code> для того же самого использования.</p>

<p> <a href="http://celeryproject.org/">celery</a> - это распределенная очередь задач, построенная на amqp (rabbitmq). он также обрабатывает периодические задачи в стиле крона (см. <a href="http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html">периодические задачи</a> ). в зависимости от вашего приложения, это может стоить того.</p><p>celery довольно легко настроить с помощью django ( <a href="http://docs.celeryproject.org/en/latest/django/">docs</a> ), и периодические задачи фактически пропускают пропущенные задачи в случае простоя. у сельдерея также есть встроенные механизмы повтора, в случае неудачи.</p>

<p>мы с открытым исходным кодом, что я думаю, является структурированным приложением. это решение брайана также намекает. буду рад любой/все отзывы!</p><p> <a href="https://github.com/tivix/django-cron">https://github.com/tivix/django-cron</a> </p><p>он поставляется с одной командой управления:</p><pre><code>./manage.py runcrons </code></pre><p>это делает работу. каждый крон моделируется как класс (так что все его оо), и каждый крон работает с разной частотой, и мы гарантируем, что один и тот же тип крона не работает параллельно (в случае, если самим кронам требуется больше времени, чем их частоте!)</p><p>спасибо!</p>

<p>если вы используете стандартную ос posix, вы используете <a href="http://linux.die.net/man/8/cron">cron</a> .</p><p>если вы используете windows, вы используете <a href="http://technet.microsoft.com/en-us/library/cc755618.aspx">at</a> .</p><p>напишите команду управления django </p><ol> <li><p>выясните, на какой платформе они работают.</p></li> <li><p>либо выполните соответствующую команду «at» для ваших пользователей, <strong>или</strong> обновите crontab для ваших пользователей.</p></li> </ol>

<p>интересное новое подключаемое приложение django: <a href="https://bitbucket.org/wnielson/django-chronograph/">django-хронограф</a> </p><p>вам нужно только добавить одну запись cron, которая действует как таймер, и у вас есть очень хороший интерфейс администратора django для запуска скриптов.</p>

<p>посмотрите на cron django poor man's, который является приложением django, которое использует спам-ботов, роботов индексации поисковых систем и т. п. для запуска запланированных задач примерно через равные промежутки времени.</p><p>смотрите: <a href="http://code.google.com/p/django-poormanscron/">http://code.google.com/p/django-poormanscron/</a> </p>

<p>rabbitmq и celery имеют больше возможностей и возможностей для обработки задач, чем cron. если сбой задачи не является проблемой, и вы думаете, что будете обрабатывать сломанные задачи в следующем вызове, то cron достаточно.</p><p>celery & <a href="https://en.wikipedia.org/wiki/advanced\_message\_queuing\_protocol">amqp</a> позволит вам обработать неработающую задачу и будет снова выполняться другим работником (сотрудники celery ожидают выполнения следующей задачи), пока не будет достигнут атрибут <code>max\_retries</code> задачи. вы даже можете вызывать задачи при сбое, например, регистрировать сбой или отправлять электронное письмо администратору после достижения <code>max\_retries</code>.</p><p>и вы можете распространять серверы celery и amqp, когда вам нужно масштабировать ваше приложение.</p>

<p>предложение брайана нила о запуске команд управления через cron работает хорошо, но если вы ищете что-то более надежное (но не такое сложное, как celery), я бы заглянул в такую библиотеку, как <a href="https://github.com/jgorset/django-kronos">kronos</a> :</p><pre><code># app/cron.py import kronos @kronos.register('0 * * * *') def task(): pass </code></pre>

<p>я лично использую cron, но <a href="http://code.google.com/p/django-command-extensions/wiki/jobsscheduling">jobs scheduling</a> parts of <a href="https://github.com/django-extensions/django-extensions">django-extensions</a> выглядит интересно.</p>

<p>поместите следующее в начало вашего файла cron.py:</p><pre><code>#!/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 </code></pre>

<p>некоторое время назад у меня было точно такое же требование, и в итоге я решил его с помощью <a href="https://apscheduler.readthedocs.io/en/latest/">apscheduler</a> ( <a href="https://apscheduler.readthedocs.io/en/latest/userguide.html">руководство пользователя</a> )</p><p>это упрощает планирование заданий и делает его независимым от выполнения кода на основе запросов. ниже приведен простой пример, который я использовал в своем коде.</p><pre><code>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 </code></pre><p>надеюсь, это кому-нибудь поможет!</p>

<p>я просто подумал об этом довольно простом решении:</p><ol> <li>определите функцию представления <strong>do\_work (req, param)</strong>, как если бы вы работали с любым другим представлением, с отображением url, возвращайте httpresponse и так далее.</li> <li>настройте задание cron с вашими настройками синхронизации (или с помощью at или запланированных задач в windows), которое запускает <strong>curl <a href="http://localhost/your/mapped/url?param=value">http: // localhost/your/mapped/url? param = value</a> </strong>.</li> </ol><p>вы можете добавить параметры, но просто добавив параметры в url.</p><p>скажите мне, что вы, ребята, думаете.</p><p><strong>[update]</strong> теперь я использую команду runjob из <a href="https://github.com/django-extensions/django-extensions">django-extensions</a> вместо curl.</p><p>мой cron выглядит примерно так:</p><pre><code>@hourly python /path/to/project/manage.py runjobs hourly </code></pre><p>... и так далее ежедневно, ежемесячно и т. д. вы также можете настроить его для запуска определенной работы.</p><p>я нахожу это более управляемым и более чистым. не требует привязки url к представлению. просто определите свой класс работы и crontab, и все готово.</p>

<p>хотя <a href="http://airflow.incubator.apache.org/project.html">airflow</a> не является частью django, это более свежий проект (по состоянию на 2016 год), который полезен для управления задачами.</p><p>airflow - это система автоматизации и планирования рабочих процессов, которую можно использовать для создания и управления конвейерами данных. веб-интерфейс предоставляет разработчику ряд возможностей для управления и просмотра этих конвейеров.</p><p>воздушный поток написан на python и построен с использованием flask.</p><p>airflow был создан максимом бочемином в airbnb и открыт с весны 2015 года. он присоединился к программе инкубации apache software foundation зимой 2016 года. вот страница проекта <a href="https://github.com/apache/incubator-airflow">git</a> и некоторые дополнения <a href="http://nerds.airbnb.com/airflow/">справочная информация</a> ,.</p>

<p>после части кода я могу написать что угодно, как и мои views.py :)</p><pre><code>####################################### 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) ####################################### </code></pre><p>от <a href="http://www.cotellese.net/2007/09/27/running-external-scripts-against-django-models/">http://www.cotellese.net/2007/09/27/running-external-scripts-against-django-models/</a> </p>

<p>вы обязательно должны проверить django-q! он не требует дополнительной настройки и, возможно, имеет все необходимое для решения любых производственных проблем коммерческих проектов.</p><p>он активно развивается и очень хорошо интегрируется с django, django orm, mongo, redis. вот моя конфигурация:</p><pre><code># 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, }, } </code></pre>

<p>у меня было что-то похожее с твоей проблемой сегодня.</p><p>я не хотел, чтобы он обрабатывался сервером через cron (и большинство библиотек в итоге были просто помощниками cron).</p><p>итак, я создал модуль планирования и прикрепил его к<strong> init </strong>.</p><p>это не лучший подход, но он помогает мне хранить весь код в одном месте, а его выполнение связано с основным приложением.</p>

<p>да, метод выше, так здорово. и я попробовал некоторые из них. наконец, я нашел такой метод:</p><pre><code> from threading import timer def sync(): do something... sync\_timer = timer(self.interval, sync, ()) sync\_timer.start() </code></pre><p>так же, как<strong> рекурсивный </strong>.</p><p>хорошо, я надеюсь, что этот метод может удовлетворить ваши требования. :)</p>

<p>я использую сельдерей для создания своих периодических заданий. сначала вам нужно установить его следующим образом:</p><pre><code>pip install django-celery </code></pre><p>не забудьте зарегистрировать <code>django-celery</code> в ваших настройках, и тогда вы сможете сделать что-то вроде этого:</p><pre><code>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 </code></pre>

<p>я не уверен, что это будет полезно для всех, так как я должен был предоставить другим пользователям системы для планирования заданий, не предоставляя им доступ к фактическому планировщику задач сервера (windows), я создал это приложение многократного использования.</p><p>обратите внимание, что пользователи имеют доступ к одной общей папке на сервере, где они могут создавать необходимые файлы command/task/.bat. эта задача может быть запланирована с помощью этого приложения.</p><p>имя приложения <a href="https://github.com/just10minutes/django\_windows\_scheduler">django\_windows\_scheduler</a> </p><p>скриншот: <a href="https://i.stack.imgur.com/y3gtf.png"> <img src="https://i.stack.imgur.com/y3gtf.png" alt="enter image description here"> </a> </p>

<p>более современным решением (по сравнению с celery) является django q: <a href="https://django-q.readthedocs.io/en/latest/index.html">https://django-q.readthedocs.io/en/latest/index.html</a> </p><p>он имеет отличную документацию и легко прогуливается. поддержка windows отсутствует, поскольку windows не поддерживает разветвление процессов. но это прекрасно работает, если вы создаете свою среду разработки, используя подсистему windows для linux. </p>

<p>если вы хотите что-то более <strong>надежное</strong>, чем <em>celery</em>, попробуйте <strong>taskhawk</strong>, построенное поверх <strong>aws sqs/sns</strong>.</p><p>см .: <a href="http://taskhawk.readthedocs.io">http://taskhawk.readthedocs.io</a> </p>

<p>простой способ - написать собственную команду shell, см. <a href="https://docs.djangoproject.com/en/2.2/howto/custom-management-commands/">документация django</a> и выполнить ее с помощью cronjob в linux. однако я очень рекомендую использовать брокер сообщений, такой как rabbitmq в сочетании с сельдереем. может быть, вы можете взглянуть на это <a href="https://simpleisbetterthancomplex.com/tutorial/2017/08/20/how-to-use-celery-with-django.html">учебник</a> </p>

<p>для простых докеризованных проектов я не мог найти подходящий ответ.</p><p>поэтому я написал очень скромное решение без необходимости использования внешних библиотек или триггеров, которое работает само по себе. не требуется внешний os-cron, он должен работать в любой среде.</p><p>это работает путем добавления промежуточного программного обеспечения: <code>middleware.py</code> </p><pre><code>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 </code></pre><p><code>models/cron.py</code>:</p><pre><code>from django.db import models class cronjob(models.model): name = models.charfield(max\_length=10, primary\_key=true) last\_ran = models.datetimefield() </code></pre><p><code>settings.py</code>:</p><pre><code>middleware = [ ... 'application.middleware.cron\_middleware', ... ] </code></pre>