I want to do a job every half an hour. My application is based on Flask, and running on Windows.
Now I create a task for the job, using Windows scheduler service.
I want to know if there is another way I can do cyclic tasks using Flask’s built-in functions...
Sorry for my poor English.
I want to know if there is another way I can do [periodic] tasks using Flask’s built-in functions.
Being somewhat a minimalist microframework, I don't think Flask has or ever will have a built-in feature to schedule periodic tasks.
The customary way is what you have already done, you write some Flask code that can be called as an HTTP endpoint or a script, then use a OS scheduling tool to execute it (e.g. Windows Task Scheduler or cron on UNIX/Linux)
Otherwise, Flask works well with other specialized libraries that take care of this, like Celery (periodic tasks) that takes care of those details and adds some features that may not be available otherwise.
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
'every-half-hour': {
'task': 'tasks.your_task',
'schedule': timedelta(minutes=30),
'args': ('task_arg1', 'task_arg2')
},
}
CELERY_TIMEZONE = 'UTC'
I m not sure if this help, but I've been testing the schedule module and it's easy to use and it works well:
$pip install schedule
and this is a sample from the official documentation:
import schedule
import time
def job():
print("I'm working...")
schedule.every(30).minutes.do(job)
while True:
schedule.run_pending()
time.sleep(1)
Hope this help =)
Related
I am in the process of writing my own task app using Django and would like a few specific functions to be executed every day at a certain time (updating tasks, checking due dates, etc.). Is there a way to have Django run functions on a regular basis or how do I go about this in general?
Does it make sense to write an extra program with an infinite loop for this or are there better ways?
Celery is a good option here:
First steps with Django
Periodic Tasks
app.conf.beat_schedule = {
'add-every-30-seconds': {
'task': 'tasks.add',
'schedule': 30.0,
'args': (16, 16)
},
}
app.conf.timezone = 'UTC'
With celery you can define periodic tasks at any given interval. Celery workers will then pick up those tasks when needed. You will need to run something like RabbitMQ or Redis to support the celery workers.
The alternative, simpler, way is to add an entry to your urls.py that catches any url you don't otherwise use, and use that as a prompt to check your database as to whether another task is due. This leverages the fact that your website will be hit by a lot of bot traffic. The timing isn't entirely reliable but it doesn't require any extra set up.
you can use django-cronjobs or maybe Schedule your job with schedule library.
I need explanation for scheduled task
I need to run task in every end of the day automatically like cron
I tried schedule app in my project
import schedule
import time
def job():
pprint.pprint("I'm working...")
schedule.every(10).minutes.do(job)
while True:
schedule.run_pending()
time.sleep(1)
when i add above code in project site was loading continuously
Question: Need to create task run automatically in background without user knowledge and without any command? It is possible?
I am new for python and django
Please suggest any idea for this task
If it is not an overkill - I recommend Celery.
It has "Celerybeat" which is like "cron"
Actually I think this is exactly what you need.
Usually you create a management command (https://docs.djangoproject.com/en/dev/howto/custom-management-commands/) and run it from a cron job.
I'm building a website which provides some information to the visitors. This information is aggregated in the background by polling a couple external APIs every 5 seconds. The way I have it working now is that I use APScheduler jobs. I initially preferred APScheduler because it makes the whole system more easy to port (since I don't need to set cron jobs on the new machine). I start the polling functions as follows:
from apscheduler.scheduler import Scheduler
#app.before_first_request
def initialize():
apsched = Scheduler()
apsched.start()
apsched.add_interval_job(checkFirstAPI, seconds=5)
apsched.add_interval_job(checkSecondAPI, seconds=5)
apsched.add_interval_job(checkThirdAPI, seconds=5)
This kinda works, but there's some trouble with it:
For starters, this means that the interval-jobs are running outside of the Flask context. So far this hasn't been much of a problem, but when calling an endpoint fails I want the system to send me an email (saying "hey calling API X failed"). Because it doesn't run within the Flask context however, it complaints that flask-mail cannot be executed (RuntimeError('working outside of application context')).
Secondly, I wonder how this is going to behave when I don't use the Flask built-in debug server anymore, but a production server with lets say 4 workers. Will it start every job four times then?
All in all I feel that there should be a better way of running these recurring tasks, but I'm unsure how. Does anybody out there have an interesting solution to this problem? All tips are welcome!
[EDIT]
I've just been reading about Celery with its schedules. Although I don't really see how Celery is different from APScheduler and whether it could thus solve my two points, I wonder if anyone reading this thinks that I should investigate more in Celery?
[CONCLUSION]
About two years later I'm reading this, and I thought I could let you guys know what I ended up with. I figured that #BluePeppers was right in saying that I shouldn't be tied so closely to the Flask ecosystem. So I opted for regular cron-jobs running every minute which are set using Ansible. Although this makes it a bit more complex (I needed to learn Ansible and convert some code so that running it every minute would be enough) I think this is more robust.
I'm currently using the awesome pythonr-rq for queueing a-sync jobs (checking APIs and sending emails). I just found out about rq-scheduler. I haven't tested it yet, but it seems to do precisely what I needed in the first place. So maybe this is a tip for future readers of this question.
For the rest, I just wish all of you a beautiful day!
(1)
You can use the app.app_context() context manager to set the application context. I imagine usage would go something like this:
from apscheduler.scheduler import Scheduler
def checkSecondApi():
with app.app_context():
# Do whatever you were doing to check the second API
#app.before_first_request
def initialize():
apsched = Scheduler()
apsched.start()
apsched.add_interval_job(checkFirstAPI, seconds=5)
apsched.add_interval_job(checkSecondAPI, seconds=5)
apsched.add_interval_job(checkThirdAPI, seconds=5)
Alternatively, you could use a decorator
def with_application_context(app):
def inner(func):
#functools.wraps(func)
def wrapper(*args, **kwargs):
with app.app_context():
return func(*args, **kwargs)
return wrapper
return inner
#with_application_context(app)
def checkFirstAPI():
# Check the first API as before
(2)
Yes it will still work. The sole (significant) difference is that your application will not be communicating directly with the world; it will be going through a reverse proxy or something via fastcgi/uwsgi/whatever. The only concern is that if you have multiple instances of the app starting, then multiple schedulers will be created. To manage this, I would suggest you move your backend tasks out of the Flask application, and use a tool designed for running tasks regularly (i.e. Celery). The downside to this is that you won't be able to use things like Flask-Mail, but imo, it's not too good to be so closely tied to the Flask ecosystem; what are you gaining by using Flask-Mail over a standard, non Flask, mail library?
Also, breaking up your application makes it much easier to scale up individual components as the capacity is required, compared to having one monolithic web application.
I am working on a Django web based project in which i need to build a application which work in the following sequence:
1) user open a page in which he need to enter a command and a time
2) Django application will execute that command at a given time on each day till user off the scheduler (by default it is True)
What i am facing the problem is that :
1) How should i execute the commands on a time but on each day. To save the commands and time i created a following model in my models.py
class commands(models.Model):
username = models.ForeignKey(User)
command = models.CharField(max_length=30)
execution_time = models.DateField()
I have the same time but i am not getting the right way to execute it on each day at the given time
and is it possible to do with pytz library?
For executing the commands i am using paramiko library
PS: I don't want to use any external library
While you could have your django app add and remove cron jobs on the system, another more django-ish approach would be to use Celery. It is a task queue system that can run both synch and async tasks.
One specific feature of Celery is scheduled tasks: http://packages.python.org/celery/userguide/periodic-tasks.html
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
"runs-every-30-seconds": {
"task": "tasks.add",
"schedule": timedelta(seconds=30),
"args": (16, 16)
},
}
They also have a more granular version of the period task that replicates the scheduling of a crontab:
from celery.schedules import crontab
CELERYBEAT_SCHEDULE = {
# Executes every Monday morning at 7:30 A.M
'every-monday-morning': {
'task': 'tasks.add',
'schedule': crontab(hour=7, minute=30, day_of_week=1),
'args': (16, 16),
},
}
Celery by itself is stand-alone but there is the django-celery specific verison
The benefit of this solution is that you do not need to edit and maintain a system-level cron tab. This is a solution that is highly integrated into django for this exact use.
Also a huge win over using a cron is that Celery can scale with your system. If you were using a basic system crontab, then the tasks would be located on the server that hosts the application. But what if you needed to ramp up your site and run it on 5 web application nodes? You would need to centralize that crontab. If you are using Celery, you have a large number of options for how to transport and store tasks. It is inherently distributed, and available in sync to all your application servers. It is portable.
It seems to me that the proper way to do this would be write a Django custom command and execute it via cron. But you seem to be under luck as others have felt similar need and have written custom django apps. Take django-cron for example.
The solution for your problem is standard cron application (task planner on *nix systems). You can schedule a script using cron (by adding it to crontab).
If your script must perform in you Django application environment, it's possible to tell him to do that with setup_environment function. You can read more about standalone scripts for Django applications here.
What is the best way to schedule a periodic task starting at specific datetime?
(I'm not using cron for this considering I've the need to schedule about a hundred remote rsyncs,
where I compute the remote vs local offset and would need to rsync each path the second the logs are generated in each host.)
By my understanding the celery.task.schedules crontab class only allows specifying hour, minute, day of week.
The most useful tip I've found so far was this answer by nosklo.
Is this the best solution?
Am I using the wrong tool for the job?
Celery seems like a good solution for your scheduling problem: Celery's PeriodicTasks have run time resolution in seconds.
You're using an appropriate tool here, but the crontab entry is not what you want. You want to use python's datetime.timedelta object; the crontab scheduler in celery.schedules has only minute resolution, but using timedelta's to configure the PeriodicTask interval provides strictly more functionality, in this case, per second resolution.
e.g. from the Celery docs
>>> from celery.task import tasks, PeriodicTask
>>> from datetime import timedelta
>>> class EveryThirtySecondsTask(PeriodicTask):
... run_every = timedelta(seconds=30)
...
... def run(self, **kwargs):
... logger = self.get_logger(**kwargs)
... logger.info("Execute every 30 seconds")
http://ask.github.com/celery/reference/celery.task.base.html#celery.task.base.PeriodicTask
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
The only challenge here is that you have to describe the frequency with which you want this task to run rather than at what clock time you want it to run; however, I would suggest you check out the Advanced Python Scheduler http://packages.python.org/APScheduler/
It looks like Advanced Python Scheduler could easily be used to launch normal (i.e. non Periodic) Celery tasks at any schedule of your choosing using it's own scheduling functionality.
I've recently worked on a task that involved Celery, and I had to use it for asynchronous operation as well as scheduled tasks. Suffice to say I resorted back to the old crontab for the scheduled task, although it calls a python script that spawns a separate asynchronous task. This way I have less to maintain for the crontab (to make the Celery scheduler run there needs some further setup), but I am making full use of Celery's asynchronous capabilities.