Reputation: 1614
I am using Django 1.11. I want to use the scheduler in my application to run my script once in a day.
This is my view.py file
from __future__ import print_function
from django.shortcuts import render
from django.utils import timezone
from django.http import HttpResponse
from datetime import datetime, timedelta
import requests
import schedule
import time
def republic(request):
return HttpResponse("<h1>Success Hindustan</h1>")
def indiatv(request):
return HttpResponse("<h1>Success Hindustan</h1>")
def ndtv(request):
return HttpResponse("<h1>Success NDTV</h1>")
schedule.every().day.at("17:19").do(republic(requests))
schedule.every().day.at("17:19").do(indiatv(requests))
schedule.every().day.at("17:19").do(ndtv(requests))
while 1:
schedule.run_pending()
time.sleep(1)
When I run the server I am getting following error
File "/home/imsaiful/PiroProject/pironews/feed/urls.py", line 2, in <module>
from . import views
File "/home/imsaiful/PiroProject/pironews/feed/views.py", line 230, in <module>
schedule.every().day.at("17:19").do(republic(requests))
File "/home/imsaiful/anaconda3/lib/python3.6/site-packages/schedule/__init__.py", line 385, in do
self.job_func = functools.partial(job_func, *args, **kwargs)
TypeError: the first argument must be callable
But when I remove the scheduler lines then the application running properly.
Upvotes: 2
Views: 6118
Reputation: 476699
By writing:
schedule.every().day.at("17:19").do(republic(requests))
schedule.every().day.at("17:19").do(republic(requests))
schedule.every().day.at("17:19").do(republic(requests))
You schedule the result of the republic(request)
as job, not "calling republic
with requests
as job".
The do(job_func, *args, **kwargs)
[schedule-doc] function however allows to provide parameters, you provide these after a reference to the job, so:
schedule.every().day.at("17:19").do(republic, requests)
schedule.every().day.at("17:19").do(republic, requests)
schedule.every().day.at("17:19").do(republic, requests)
You can not run the scheduler this way in Django, since it will mean that you keep running the command when loading the file. So loading the file will never terminate, and hence the server will never start.
You can run the scheduler asynchronous however, with:
from threading import Thread
from __future__ import print_function
from django.shortcuts import render
from django.utils import timezone
from django.http import HttpResponse
from datetime import datetime, timedelta
import requests
import schedule
import time
def republic(request):
return HttpResponse("<h1>Success Hindustan</h1>")
schedule.every().day.at("17:19").do(republic, requests)
schedule.every().day.at("17:19").do(republic, requests)
schedule.every().day.at("17:19").do(republic, requests)
class SchedulerThread(Thread):
@classmethod
def run(cls):
while True:
schedule.run_pending()
time.sleep(interval)
ScheduleThread().start()
Finally note that requests
is not a HttpRequest
object, so you should not write your functions as views, but as "vanilla" functions that perform certain work.
Upvotes: 1
Reputation: 1323
republic(requests) will return HttpResponse,
so the execution would be
schedule.every().day.at("17:19").do(HttpResponse)
inside do
method you should mention function, not class instance.
you can use one of the below
solution 1:
schedule.every().day.at("17:19").do(lambda: republic(requests))
solution 2.
schedule.every().day.at("17:19").do(republic, requests)
solution 3.
import functools
schedule.every().day.at("17:19").do(functools.partial(republic, requests))
Upvotes: 4
Reputation:
based on the schedule.Job.do, you should pass args after the function:
schedule.every().day.at("17:19").do(republic, requests)
schedule.every().day.at("17:19").do(indiatv, requests)
schedule.every().day.at("17:19").do(ndtv, requests)
do(job_func, *args, **kwargs)
Specifies the job_func that should be called every time the job runs. Any additional arguments are passed on to job_func when the job runs.
Upvotes: 2