Django cron is not running using crontab - python

I have made a file named updatefield.py content is
from FrontEnd.views import UpdateField
def my_scheduler():
# add logic
UpdateField()
I have put it inside my project root with manage.py file
And my settings.py file is like
CRONJOBS = [
('* * * * *', 'Ravi.updatefield.my_scheduler')
]
Installed apps
'django_cron',
'django_crontab',
After executing command python manage.py crontab add I got
adding cronjob: (33083f0c14f7cccdc5851431976adcbb) -> ('* * * * *', 'Ravi.updatefield.my_scheduler')
But its not running Right now . And noting is appearing on my terminal my function is this
def UpdateField(request):
print('hi')
return HttpResponse('hello world')

Related

Settings in Django run repeat when runserver

I don't know why my django app run settings/base.py 2 times. I think it would make my app slow down
In my settings/base.py I printed
print('this is base_dir')
print(BASE_DIR)
output is:
this is base_dir
F:\7.Django\BLOG_PROJECT\src_blog
this is base_dir
F:\7.Django\BLOG_PROJECT\src_blog
This is my settings file:
├── settings
| ├──__init__.py
| ├──base.py
| ├──dev.py
| ├──prod.py
and my settings\__init__.py file contain:
import os
from dotenv import load_dotenv
load_dotenv()
if os.environ['ENV_SETTING'] =='prod':
from .prod import *
else:
from .dev import *
from .base import *
This is probably related to the good old double thread spawning in Django. The way Django is setup it spawns two threads at the start, so one process is there to process requests and the other to watch if you changed any code so it can respawn the first one.
If you print the following in settings.py
import os
print(os.getpid())
You would see that it prints 2 different values. This is a standard django behaviour as far as I know.

Python crontab adding newline character automatically and disabling other cron job

I've written a python script to run certain cron jobs and using crontab for the same.
Following is the code snippet:
import os
import inspect
from crontab import CronTab
def add_cron_job(scripts_list,frequency):
my_cron = CronTab(user='simrat')
for script in scripts_list:
if not cron_exists(my_cron,script):
command = 'python {}'.format(script)
job = my_cron.new(command=command, comment=script)
job.minute.every(frequency)
my_cron.write()
def cron_exists(my_cron, script):
for job in my_cron:
if job.comment == script:
return True
return False
if __name__ == "__main__":
#Frequency of every 1 minute
test_script = ['test1.py', 'test2.py']
add_cron_job(test_script,1)
#Frequency of every 1 day
test_script2 = ['test3.py']
add_cron_job(test_script2,1440)
Following is the output of 'crontab -e' (notice additional spaces added)
* * * * * python test1.py # test1.py
* * * * * python test2.py # test2.py
*/1440 * * * * python test3.py # test3.py
When I re-run the python cron_job script, it somehow disables the last cron_job(test3.py) and following is the output of crontab file:
* * * * * python test1.py # test1.py
* * * * * python test2.py # test2.py
# DISABLED LINE
# */1440 * * * * python test3.py # test3.py
*/1440 * * * * python test3.py # test3.py
along with an error it throws on console:
No handlers could be found for logger "crontab"
So my question is 3 fold:
Why is additional space at the top of the command when running my_cron.write()?
Why does it disable the last cron job instead of ignoring it as it already exists (def cron_exits should have taken care of that)
What's the signifance of the error thrown?
I ran you code and got following error in second run:
'1440', not in 0-59 for Minutes
I changed 1440 to 14 and ran code multiple times. And found same code every time (without deleting)
* * * * * python test1.py # test1.py
* * * * * python test2.py # test2.py
*/14 * * * * python test3.py # test3.py
I have not read complete CronTab code but it is clear that they have put some validator during reading existing cron commands but they are not validating it during writing.
Also i called add_cron_job with different arguments and found each time my_cron.write() is called it is adding a new line. This is not a bug but a feature.
Finally
No handlers could be found for logger "crontab" is logging issue. Try this Crontab Logger issue

Crontab python django issue

The following works as expected:
python /usr/share/str8RED/manage.py getLiveResults
However, nothing happens when I use the following cronjob:
*/1 * * * * python /usr/share/str8RED/manage.py getLiveResults
Using the link below I have managed to create a error log:
http://matthewwittering.com/blog/django-tips/running-a-django-management-commands-with-crontab.html
This informs me that:
Traceback (most recent call last):
File "/usr/share/str8RED/manage.py", line 8, in <module>
from django.core.management import execute_from_command_line
ImportError: No module named django.core.management
I can get cronjab working and running every minute with echo "Hello World". Any help would be appreciated, many thanks, Alan.
Contents of getLiveResults.py:
from django.core.management import BaseCommand
from straightred.models import StraightredTeam
from straightred.xmlsoccer import XmlSoccer
#The class must be named Command, and subclass BaseCommand
class Command(BaseCommand):
# Show this when the user types help
help = "My test command"
# A command must define handle()
def handle(self, *args, **options):
xmlsoccer = XmlSoccer(api_key='XYZ', use_demo=False)
teams = xmlsoccer.call_api(method='GetAllTeamsByLeagueAndSeason',
seasonDateString='1617',
league='English League Championship')
numberOfTeamsUpdated = 0
for team in teams:
if '{http://xmlsoccer.com/Team}Team_Id' in team.keys():
teamUpdate = StraightredTeam(teamid=team['{http://xmlsoccer.com/Team}Team_Id'],
teamname=team['{http://xmlsoccer.com/Team}Name'],
country=team['{http://xmlsoccer.com/Team}Country'],
stadium=team['{http://xmlsoccer.com/Team}Stadium'],
homepageurl=team['{http://xmlsoccer.com/Team}HomePageURL'],
wikilink=team['{http://xmlsoccer.com/Team}WIKILink'],
currentteam=1)
teamUpdate.save()
numberOfTeamsUpdated = numberOfTeamsUpdated + 1
self.stdout.write("Hello world!")
If you are using virtual env, then you need to activate the environment,
maybe something like:
*/1 * * * * /usr/share/str8RED/.env/bin/python /usr/share/str8RED/manage.py getLiveResults

How to run python file in cron job

I need to run this file:
from apps.base.models import Event
from apps.base.models import ProfileActiveUntil
from django.template import Context
from django.db.models import Q
import datetime
from django.core.mail import EmailMultiAlternatives
from bonzer.settings import SITE_HOST
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from bonzer.settings import send_mail, BONZER_MAIL, BONZER_MAIL_SMTP, BONZER_MAIL_USER, BONZER_MAIL_PASS, BONZER_MAIL_USETLS
today = datetime.date.today()
monthAgo = today + datetime.timedelta(days=1)
monthAgoMinusOneDay = today + datetime.timedelta(days=2)
events = Event.objects.all()
ProfileActiveUntils = ProfileActiveUntil.objects.filter(Q(active_until__range=(monthAgo, monthAgoMinusOneDay)))
msg = MIMEMultipart('alternative')
msg['Subject'] = "Novim dogodivscinam naproti"
msg['From'] = BONZER_MAIL
msg['To'] = 'jjag3r#gmail.com'
text = u'bla'
html = u'bla'
send_mail(msg_to=msg['To'], msg_subject=msg['Subject'], msg_html=html, msg_text=text)
I execute it like this: */2 * * * * /usr/local/bin/python2.7 /home/nezap/webapps/bonzer/bonzer/apps/base/alert.py
But I get error: No module named apps.base.models.
Important fact is that I can't install virtualenv on server because I don't have permissions. Also I'm kind of newbie on this stuff so I don't have a lot of skills on servers or python.
Thank you.
cron does not read rc shell files so you need to define the enviroment variable PYTHONPATH to include the location of the apps package and all other module files that are required by the script.
PYTHONPATH=/usr/local/lib/python2.7:/usr/lib/python2.7
*/2 * * * * /usr/local/bin/python2.7 /home/nezap/webapps/bonzer/bonzer/apps/base/alert.pyr
I would assume this is a problem with your cwd (current working directory). An easy way to test this would be to go to the root (cd /) then run:
python2.7 /home/nezap/webapps/bonzer/bonzer/apps/base/alert.py
You should get the same error. The path you will want to use will depend on the place where you normally run the script from. I would guess it would either be:
/home/nezap/webapps/bonzer/bonzer/apps/base
or
/home/nezap/webapps/bonzer/bonzer/
So your solution would either be:
*/2 * * * * cd /home/nezap/webapps/bonzer/bonzer/apps/base && /usr/local/bin/python2.7 ./alert.py
or
*/2 * * * * cd /home/nezap/webapps/bonzer/bonzer && /usr/local/bin/python2.7 ./apps/base/alert.py
basically you are telling cron to change directory to that path, then if that works(the &&) run the following command.

Django unit testing - Why can't I just run ./tests.py on myApp?

So I'm very familiar with manage.py test myapp. But I can't figure out how to make my tests.py work as an stand-alone executable. You may be wondering why I would want to do this.. Well I'm working (now) in Eclipse and I can't seem to figure out how to set up the tool to simply run this command. Regardless it would be very nice to simply wrap tests.py in a simple manner to just run that.
Here is what my tests.py looks like.
"""
This simply tests myapp
"""
import sys
import logging
from django.test import TestCase
from django.conf import settings
from django.test.utils import get_runner
class ModelTest(TestCase):
def test_model_test1(self):
"""
This is test 1
"""
self.failUnlessEqual(1 + 1, 2)
def test_model_test2(self):
"""
This is test 2
"""
self.failUnlessEqual(1 + 1, 2)
def test_model_test3(self):
"""
This is test 3
"""
self.failUnlessEqual(1 + 1, 2)
def run_tests():
test_runner = get_runner(settings)
failures = test_runner([], verbosity=9, interactive=False)
sys.exit(failures)
if __name__ == '__main__':
# Setup Logging
loglevel = logging.DEBUG
logging.basicConfig(format="%(levelname)-8s %(asctime)s %(name)s %(message)s",
datefmt='%m/%d/%y %H:%M:%S', stream=sys.stdout)
log = logging.getLogger("")
run_tests()
I think the solution is located on this line but I can't seem to figure out what the first argument needs to be in order for it to magically start working..
failures = test_runner([], verbosity=9, interactive=False)
Thanks for helping!!
**** Updates ****
What I am looking to do (Doh!) is to simply run "myApp" tests. The problem is that this works (and chmod is not the problem) but it wants to run the entire test suite. I don't want that. I just want to run the myApp test suite.
Thanks again!
You could create an "External Tool" configuration for your project, such as:
Location: ${project_loc}/src/${project_name}/manage.py
Working Directory: ${project_loc}/src/${project_name}/
Arguments: test ${string_prompt}
This will run manage.py test <whatever name you type in the string prompt>.
The values above assume that you created a pydev project in Eclipse and then housed your Django project in the pydev src directory. It also assumes that you have the project name for pydev be the same name of your Django project. It will use the currently selected project in the package explorer to determine project_loc and project_name.
a. this should be the first line at your code file (tests.py)
#!/usr/bin/env python
b. run $ chmod +x tests.py

Categories

Resources