I have a Django web app which is used by embedded systems to upload regular data, currently every 2 minutes, to the server where Django just pops it into a database.
I'd like to create an alert system where by if there's no data uploaded from the remote system in a time period, say 10 minutes for example, I raise an alarm on the server, via email or something.
In other programming languages/environments I'd create a 10 minute timer to execute a function in 10 minutes, but every time data is uploaded I'd restart the timer. Thus hopefully the timer would never expire and the expiry function would never get called.
I might well have missed something obvious but if there is something I have missed it. This just does not seem possible in Python. Have I missed something?
At present looks like I need an external daemon monitoring the database :-(
You could use the time module for this:
import time
def didEventHappen():
# insert appropriate logic here to check
# for what you want to check for every 10 minutes
value = True # this is just a placeholder so the code runs
return value
def notifyServer():
print("Hello server, the event happened")
start = time.clock()
delay = 10 * 60 # 10 minutes, converted to seconds
while True:
interval = time.clock() - start
eventHappened = False
if interval >= delay:
eventHappened = didEventHappen()
start = time.clock() # reset the timer
if eventHappened:
notifyServer()
else:
print("event did not happen")
Alternatively, you could use the sched module.
Related
I'm creating HMI web application which visualise realtime data from simulation.
It means I'm updating data every 0.25/0.5 seconds. I decided to use socket.io.
So I want my server after connection to emit data every some period of time. I thought the best option would be emitting data in something similar like setInterval in JavaScript. However, in python this has not proved too easy. I tried a lot of options from stackoverflow f.e:
Python Equivalent of setInterval()?
But most of them are causing errors. Here are some methods which I tried.
#socketio.on('signalList')
def start_polling_signals():
global poll_signals
poll_signals = threading.Timer(1000, start_polling_signals())
poll_signals.start()
list_signals_v2()
print('polling')
#socketio.on('stopSignalList')
def stop_polling_signals():
global poll_signals
poll_signals.cancel()
poll_signals = None
Causes maximum recursion depth exceeded
#socketio.on('signalList')
def start_polling_signals():
starttime = time.time()
while True:
list_signals_v2()
time.sleep(1 - ((time.time() - starttime) % 1))
Causes that other socket events don't work, and I have no idea how to stop that polling.
Any ideas how to do it in optimal way? Have in mind I need to be able to start and stop the interval.
You should start a background task using the
start_background_task(target, *args, **kwargs)
This is the correct way to init something like what you want to do. Pass as target a function that will send data in the period of time you want it to send data.
Is it possible make this .py script time out every 20 minutes and auto run again by it self?
Currently I'm using crontab to rerun it every 20 minutes but the thing is it's running multiple .py sometime and not actually rerunning the program. I just want it to rerun every 20 minutes not rerun another instance of it every 20 minutes.
#!/usr/bin/env python
from TwitterFollowBot import TwitterBot
my_bot = TwitterBot("/home/TwitterFollowBot/config.txt")
my_bot.sync_follows()
my_bot.auto_unfollow_nonfollowers()
my_bot.auto_rt("#RtwtKing", count=2000)
my_bot.auto_rt("#ShoutGamers", count=2000)
You have several ways to do this.
If you want to do it only with Python you can:
Use threads, it will work pretty well, but it's not really what threads are designed for.
Use Daemon (good example here)
Do a Python wrapper which will loop forever and call you script when needed. It's less clean, but less overkill too.
Example of the wrapper solution:
The goal is to create a new python script which will handle timer and so execute your Twitter code when needed.
1. Update your current code to encapsulate it in a method
let's say your current file is named core.py
core.py:
from datetime import datetime
from TwitterFollowBot import TwitterBot
def get_feed():
print "({}) LOG: get_feed starting".format(datetime.now())
my_bot = TwitterBot("/home/TwitterFollowBot/config.txt")
my_bot.sync_follows()
my_bot.auto_unfollow_nonfollowers()
my_bot.auto_rt("#RtwtKing", count=2000)
my_bot.auto_rt("#ShoutGamers", count=2000)
This just make your code in a function and add a logging line which print current time when function is executed.
2. Make a wrapper which handle timer and call your twitter code
wrapper.py:
import time
from datetime import datetime
# Import your twitter code, so you can use it by calling 'get_feed()'
from core import get_feed
# Define constants here because it's easier to find it on top of file
# Delta between the last call and the next one, bascially time between two calls: 20 minutes
DELTA = 20 * 60
# Time your wrapper will take between each verification: 5 minutes
SLEEP_TIME = 5 * 60
# Initialize timer and call for the first time your method
# last_run will store timestamp of the last time you called get_feed()
last_run = time.time()
get_feed()
# Start an inifinite loop
while True:
# Compute delta since last call
# last_run_delta will store the time in seconds between last call and now
last_run_delta = time.time() - last_run
# If last_run_delta is upper than DELTA so the number of seconds you want to separate two calls is reached.
if last_run_delta >= DELTA:
# Because time is reached you want to run again your code and reset timer to can handle next call
last_run = time.time()
get_feed()
# If you have not reach delta time yet, you want to sleep to avoid stack overflow and because you don't need to check each microseconds
else:
time.sleep(SLEEP_TIME)
Ouput with DELTA = 10 and SLEEP_TIME = 5 (core.py is called every 10 seconds and check is done each 5 seconds):
(2016-11-29 10:43:07.405750) LOG: get_feed starting
(2016-11-29 10:43:17.414629) LOG: get_feed starting
(2016-11-29 10:43:27.422033) LOG: get_feed starting
(2016-11-29 10:43:37.430698) LOG: get_feed starting
(2016-11-29 10:43:47.436595) LOG: get_feed starting
The only real good point with this method is you can't launch same process two times at once. Because it's not asynchronous, get_feed can't be called twice, but if get_feed take more time than SLEEP_TIME or DELTA you will miss some calls and so do not run it each 20min.
Last thing, because you are importing core.py in wrapper.py you have to create a __init__.py file in the same folder than the two others files. (/path/to/project/ should contains __init__.py (empty), core.py and wrapper.py).
The real good way will is to create a daemon, but it require more skills.
I was working with the Tornado webserver and wanted to understand on how to determine if the server has been idle for a while and then restart it.
I was trying to determine the time difference between self.requests to determine if no request has been received for a while. But is there a better way to do it?
One simple way is to use a global variable to hold the timestamp of the last request and update it whenever you process requests. Something like:
#startup initialization code
_last_request = datetime.datetime.now()
#we will use these variables later
interval = datetime.timedelta(seconds=30)
idle_timeout = datetime.timedelta(seconds=1800)
...
#update timestamp in handler(s)
global _last_request
_last_request = datetime.datetime.now()
You will then add a function which checks from time to time the _last_request variable:
def idle_check():
if _last_request - datetime.datetime.now() > idle_timeout:
#stop the IOLoop
tornado.ioloop.IOLoop.instance().stop()
else:
#schedule to run again
tornado.ioloop.IOLoop.instance().add_timeout(interval, idle_check)
Do not forget to call the idle_check function before starting the IOLoop.
I would like to implement a cron-like behaviour with my twisted application.
I want to trigger a periodic call (let's say every week) but running at a precise time only, not when i start my application.
My use case is the following:
my python application is started at any time in the week. I want the calls to be performed every monday at 8am.
But I don't want to perorm active waiting (using a time.sleep()), i would like to use callLater to trigger the call next monday and then start a looping call from that date.
any idea/advice?
thanks,
J.
If you are absolutely in love with cron-style specifiers, you could also consider using parse-crontab
Then your code looks basically like:
from crontab import CronTab
monday_morning = CronTab("0 8 * * 1")
def do_something():
reactor.callLater(monday_morning.next(), do_something)
# do whatever you want!
reactor.callLater(monday_morning.next(), do_something)
reactor.run()
If I understood your question correctly you are thinking of first time execution of a scheduled task and how to supply initial start time for the app. If this is a case, you just need to calculate timedelta value in seconds to be passed to callLater.
import datetime
from twisted.internet import reactor
def cron_entry():
full_weekseconds = 7*24*60*60
print "I was called at a specified time, now you can add looping task with a full weekseconds frequency"
def get_seconds_till_next_event(isoweekday,hour,minute,second):
now = datetime.datetime.now()
full_weekseconds = 7*24*60*60
schedule_weekseconds = ((((isoweekday*24)+hour)*60+minute)*60+second)
now_weekseconds=((((now.isoweekday()*24)+now.hour)*60+now.minute)*60+now.second)
if schedule_weekseconds > now_weekseconds:
return schedule_weekseconds - now_weekseconds
else:
return now_weekseconds - schedule_weekseconds + full_weekseconds
initial_execution_timedelta = get_seconds_till_next_event(3,2,25,1)
"""
This gets a delta in seconds between now and next Wednesday -3, 02 hours, 25 minutes and 01 second
"""
reactor.callLater(initial_execution_timedelta,cron_entry)
reactor.run()
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the best way to repeatedly execute a function every x seconds in Python?
Hi so here is the code I have:
client = myclient(info1,info2)
sellor()
Contractor()
It works perfectly but what I would like to do is to make python launch that code every 60 seconds indefinitely...
I don't actually understand how I have to put the code together with the time loop
Any help is appreciated
Thank's
If the 60 seconds ignores the time it takes to execute your code):
from time import sleep
while True:
sleep(60)
# your code here
but if the 60 seconds takes into account the time it takes to execute your code:
from time import sleep
from os import fork
while True:
sleep(60)
fork() # create child process
# your code here
Use the sleep method. Just create a loop (while, for, whatever) and sleep for 60 secs every iteration.
import time
while True:
client = myclient(info1,info2)
sellor()
Contractor()
time.sleep(10)
hope it works,all the best mate
import time
repeat_time = 3.0
while True:
start_time = time.time()
# Your code goes here
time.sleep(max(repeat_time - (time.time() - start_time), 0.0))
And your code will be executed exactly every "repeat_time"
You could use sleep as already mentioned. But because there may be a variable amount of time needed for your own functions to run, this wouldn't necessarily mean your functions are run every 60 seconds.
If it was important that the period between each start of your functions is closer to 60 seconds, you could use time. I haven't tried this but something like
import time
while True:
# Get the current time
startTime = time.time()
# Your functions
client = myclient(info1,info2)
sellor()
Contractor()
delay = True
while delay:
if time.time() - startTime > 60:
delay = False # Break the delay
You might also think of just scheduling the task through windows scheduler. The benefit here would end the script once run and then execute the script again after scheduled interval. In the second approach it seems that the script instance process would continually run and only use the sleep function to do nothing for the specified time. I take it this way if the scripts fails at any instance you might have to keep a check to restart the script. While as a scheduled activity the script will be executed in any case at that specified intervals.
You might also not want the process thread to be kept running for the python script executed. I will research on this and you might get to hear form our other folks in the mean while.
Regards,
Harshal