Pause for loop every x minutes [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
How can I create a loop that sleeps a random amount of time every X minutes, where X is also a random duration of time?
I also want to be able to specify the upper and lower boundaries of the random durations of both times.

You could try something like this:
import random
from datetime import datetime
from time import sleep
# Randomly select a time between 20 to 30 minutes
# before sleeping.
random_time_duration = random.randint(1200,1800)
# Randomly sleep between 60 to 120 seconds.
sleep_duration = random.randint(60,120)
# This is the start time of of loop used to track
# how much time has passed.
old_time = datetime.now()
while True:
# Check if the randomly selected duration has
# passed before running your code block.
if (datetime.now()-old_time).total_seconds() > random_time_duration:
sleep(sleep_duration)
# Reset all the time variables so the loop works
# again.
random_time_duration = random.randint(1200,1800)
sleep_duration = random.randint(60,120)
old_time = datetime.now()
else:
# Put your code in here.
pass

sleep_time = 50 #time to sleep in seconds
difference = 30
sleep_time = random.randint(sleep_time-difference, sleep_time+difference)
sleep_every = 10 #ammount of time to wait before sleeping in minutes
cur_time = time.time()
while True: #change to your for loop
if time.time() - cur_time >= sleep_time * 60:
time.sleep(sleep_time)
cur_time = time.time()
else:
#your code here
print time.time() - cur_time
can obviously be adapted to a function but this works perfectly

here is a sample code using datetime.now() and timedeltas to calculate the next interval somewhat randomly, this has an advantage over using time.time or similar since that would fail at midnight since the date would also be important in that case:
import time
import random
import datetime
sleep_duration = 1 #seconds
min_sleep_interval = max_sleep_interval = 3 #in seconds
_TIME_TO_SLEEP = datetime.datetime.now()
def maybe_sleep():
#using a singleton class you could avoind using globals
global _TIME_TO_SLEEP
if datetime.datetime.now()>= _TIME_TO_SLEEP:
time.sleep(sleep_duration)
seconds_to_wait = random.randint(min_sleep_interval, max_sleep_interval)
next_delay = datetime.timedelta(seconds= seconds_to_wait)
_TIME_TO_SLEEP = datetime.datetime.now() + next_delay
Then just call maybe_sleep() every iteration and adjust the constants to your liking (maybe make them less constant ;)
As a demo:
for i in range(10000):
maybe_sleep()
print(i)

You can try this :
import datetime
import time
import random
sleep_duration = 60
previous_sleep = datetime.datetime.now()
random_offset = random.randint(-5, 5)
while(True):
delta = (datetime.datetime.now() - previous_sleep).total_seconds()
if delta < 60 * (20 + random_offset):
# Do stuff
time.sleep(1)
continue
else:
previous_sleep = datetime.datetime.now()
random_offset = random.randint(-5, 5)
time.sleep(sleep_duration)
This program would sleep for 60 seconds every 15-25 minutes, depending on the random offset computed.

Related

How can I write a loop to make the timer run every two seconds

I have a question on how I am able to set the timer so that every time it exits the loop it sets the time back to 2 seconds. The problem is that the first time the sound works after 2 seconds, the next times it is executed immediately. Thank you very much in advance for any advice.
This is my code:
time = 2
while time > 0:
timer = datetime.timedelta(seconds=time)
time -= 1
duration = 1000
freq = 440
winsound.Beep(freq, duration)
I am not sure if you meant that, but for me it seems like you just want to wait 2 seconds before executing the next steps. You can do that like so:
import time
while True:
time.sleep(2) # waits 2 seconds
winsound.Beep(440, 1000)
Anyways I don't recommend you to use a plain infinite loop, without a break statement. Therefore I recommend you to add one, like down below.
import time
while True:
time.sleep(2) # waits 2 seconds
winsound.Beep(440, 1000)
if True: # break on a specific statment
break
Edit: As CrazyChucky mentioned in the comments, this approach should work fine in most of the cases, but it can end up being more than two seconds sometimes. Therefore you should work with timedeltas or take a look at scheduler.
To be more accurate as possible use:
import time
timer = 0
step = 2
t0 = time.time()
while True:
timer = time.time() - t0
wait = step - timer
time.sleep(wait)
print(time.time())
winsound.Beep(freq, duration)
t0 = time.time()
This script take in count the execution time of script lines for your computer.
You just have to reinitialize the time at the end of the loop
time = 2
while True:
timer = datetime.timedelta(seconds=time)
time -= 1
duration = 1000
freq = 440
if time == 0:
time = 2
break
winsound.Beep(freq, duration)

How to restart current seconds to 59 and start counting down

I'm trying to make a break timer. I can get the current second value, but I don't know how to reset the seconds and start counting down
I've tried several formulas found here on stack overflow, but have yet to find what I'm looking for
import time
while True:
now = time.localtime(time.time())
print(now[5])
time.sleep(1)
I expect the output to count down from 59 and start over
output: count up from current second
Why don't you use something like:
import time
sec = 0
while True:
print(59 - sec)
time.sleep(1)
sec = (sec + 1) % 60
Here is version with a defined function. It will countdown at defined seconds, taking sleep every seconds.
import time
def countdown(t_sec):
while t_sec:
mins, secs = divmod(t_sec, 60)
timeformat = '{:02d}'.format(secs)
print(timeformat)
time.sleep(1)
t_sec -= 1
countdown(59)

How can I know in Python how many times a line of code is executed per minute?

For example if I have:
something=something+1
I want to know how many times in a minute, this line is executed in order to create another variable with this result?
I suppose you are trying to do some basic benchmarking, in this case it would go like this:
import time
start = int(round(time.time() * 1000))
something = 0
while something < 1000000:
something = something + 1
delta = int(round(time.time() * 1000)) - start
print "loop ran 1000000 times in {0:0d} milliseconds".format(delta)
If you are willing to wait a full minute (which usually is not the case) you could do something like
import time
start = time.time()
operationsPerMinute = 0
while (time.time() - start < 60):
operationsPerMinute = operationsPerMinute + 1
print(operationsPerMinute)
In which case operationsPerMinute holds the value you want.
Alternatively, you could run in a much smaller time frame and use a bit of math to estimate it in a whole minute time frame.
For benchmarking you would probably ask for per second timings.
To count events in the last minute, here is a class remembering event timestamps for a given period:
import bisect
import time
class TimedCounter:
def __init__(self, period=60.0):
self._timestamps = []
self._period = period
def _cleanup(self, now):
del self._timestamps[:bisect.bisect_left(self._timestamps, now - self._period)]
def increment(self):
now = time.time()
self._timestamps.append(now)
self._cleanup(now) # optimization: not necessary to call every time
def get_count(self):
self._cleanup(time.time())
return len(self._timestamps)
and an example:
tc = TimedCounter(1.0)
for i in range(7, 27):
tc.increment()
print("{} time(s) in the last second".format(tc.get_count()))
time.sleep(7/i)

How to make a proper server tick?

I am trying to make a game server which updates after a certain period.
import time
last_time = time.time()
tick = 1
time_since_last_update = 0
while True:
new_time = time.time()
dt = new_time - last_time
time_since_last_update += dt
last_time = new_time
if time_since_last_update > tick:
print("Magic happens")
time_since_last_update = 0
When I do this thing, python consumes 100% computing power on one of the cores. I don't really understand why is this happening and how to fix this if possible.
Insert a time.sleep(0.01) to wait 10 millis between each time poll otherwise your loop polls time continuously without releasing power to the cpu.
Edit: That is better, only waits once if needed. Should a huge CPU overload occur, the time to wait could be negative, and in that case 2 actions could be triggered at once.
And targeted time is recomputed constantly to avoid float accumulation errors.
import time
start_time = time.time()
tick = 1.0 # 1 second
tick_count = 0
while True:
new_time = time.time()
tick_count += 1
targeted_time = start_time + tick*tick_count
time_to_wait = targeted_time - new_time
if time_to_wait>0:
time.sleep(time_to_wait)
print("Magic happens,waited %f seconds" % time_to_wait)

Generate some "random" start times for scripts to run based on a period of time in python

I'm trying to generate some random seeded times to tell my script when to fire each of the scripts from within a main script.
I want to set a time frame of:
START_TIME = "02:00"
END_TIME = "03:00"
When it reaches the start time, it needs to look at how many scripts we have to run:
script1.do_proc()
script2.alter()
script3.noneex()
In this case there are 3 to run, so it needs to generate 3 randomized times to start those scripts with a minimum separation of 5 mins between each script but the times must be within the time set in START_TIME and END_TIME
But, it also needs to know that script1.main is ALWAYS the first script to fire, other scripts can be shuffled around (random)
So we could potentially have script1 running at 01:43 and then script3 running at 01:55 and then script2 might run at 02:59
We could also potentially have script1 running at 01:35 and then script3 running at 01:45 and then script2 might run at 01:45 which is also fine.
My script so far can be found below:
import random
import pytz
from time import sleep
from datetime import datetime
import script1
import script2
import script3
START_TIME = "01:21"
END_TIME = "03:00"
while 1:
try:
# Set current time & dates for GMT, London
CURRENT_GMTTIME = datetime.now(pytz.timezone('Europe/London')).strftime("%H%M")
CURRENT_GMTDAY = datetime.now(pytz.timezone('Europe/London')).strftime("%d%m%Y")
sleep(5)
# Grab old day for comparisons
try:
with open("DATECHECK.txt", 'rb') as DATECHECK:
OLD_DAY = DATECHECK.read()
except IOError:
with open("DATECHECK.txt", 'wb') as DATECHECK:
DATECHECK.write("0")
OLD_DAY = 0
# Check for new day, if it's a new day do more
if int(CURRENT_GMTDAY) != int(OLD_DAY):
print "New Day"
# Check that we are in the correct period of time to start running
if int(CURRENT_GMTTIME) <= int(START_TIME.replace(":", "")) and int(CURRENT_GMTTIME) >= int(END_TIME.replace(":", "")):
print "Correct time, starting"
# Unsure how to seed the start times for the scripts below
script1.do_proc()
script2.alter()
script3.noneex()
# Unsure how to seed the start times for above
# Save the current day to prevent it from running again today.
with open("DATECHECK.txt", 'wb') as DATECHECK:
DATECHECK.write(CURRENT_GMTDAY)
print "Completed"
else:
pass
else:
pass
except Exception:
print "Error..."
sleep(60)
EDIT 31/03/2016
Let's say I add the following
SCRIPTS = ["script1.test()", "script2.test()", "script3.test()"]
MAIN_SCRIPT = "script1.test()"
TIME_DIFFERENCE = datetime.strptime(END_TIME, "%H:%M") - datetime.strptime(START_TIME, "%H:%M")
TIME_DIFFERENCE = TIME_DIFFERENCE.seconds
We now have the the number of scripts to run
We have the list of the script to run.
We have the name of the main script, the one to run first.
We have the time in seconds to show how much time we have in total to run all the scripts within.
Surely there is a way we can just plug some sort of loop to make it do it all..
for i in range(len(SCRIPTS)), which is 3 times
Generate 3 seeds, making sure the minimum time is of 300 and all together the 3 seeds must not exceed TIME_DIFFERENCE
Create the start time based on RUN_TIME = START_TIME and then RUN_TIME = RUN_TIME + SEED[i]
First loop would check that that MAIN_SCRIPT exists within SCRIPTS, if it does then it would run that script first, delete itself from SCRIPTS and then on next loops, as it doesn't exist in SCRIPTS it would switch to randomly calling one of the other scripts.
Seeding the times
The following appears to work, there might be an easier way of doing this though.
CALCULATE_SEEDS = 0
NEW_SEED = 0
SEEDS_SUCESSS = False
SEEDS = []
while SEEDS_SUCESSS == False:
# Generate a new seed number
NEW_SEED = random.randrange(0, TIME_DIFFERENCE)
# Make sure the seed is above the minimum number
if NEW_SEED > 300:
SEEDS.append(NEW_SEED)
# Make sure we have the same amount of seeds as scripts before continuing.
if len(SEEDS) == len(SCRIPTS):
# Calculate all of the seeds together
for SEED in SEEDS:
CALCULATE_SEEDS += SEED
# Make sure the calculated seeds added together is smaller than the total time difference
if CALCULATE_SEEDS >= TIME_DIFFERENCE:
# Reset and try again if it's not below the number
SEEDS = []
else:
# Exit while loop if we have a correct amount of seeds with minimum times.
SEEDS_SUCESSS = True
Use datetime.timedelta to compute time differences. This code assumes all three processes run on the same day
from datetime import datetime, timedelta
from random import randint
YR, MO, DY = 2016, 3, 30
START_TIME = datetime( YR, MO, DY, 1, 21, 00 ) # "01:21"
END_TIME = datetime( YR, MO, DY, 3, 0, 0 ) # "3:00"
duration_all = (END_TIME - START_TIME).seconds
d1 = ( duration_all - 600 ) // 3
#
rnd1 = randint(0,d1)
rnd2 = rnd1 + 300 + randint(0,d1)
rnd3 = rnd2 + 300 + randint(0,d1)
#
time1 = START_TIME + timedelta(seconds=rnd1)
time2 = START_TIME + timedelta(seconds=rnd2)
time3 = START_TIME + timedelta(seconds=rnd3)
#
print (time1)
print (time2)
print (time3)
Values of rnd1, rnd2and rnd3 are at least 5 minutes (300 seconds) apart.
Values of rnd3 cannot be greater than the total time interval (3 * d1 + 600). So all three times occur inside the interval.
NB You did not specify how much time each script runs. That is why I did not use time.sleep. A possible option would be threading.Timer (see python documentation).
Assume you store all the method.func() in an array and, as u described, subsequent scripts must be at least 5 mins after script1. They can be executed randomly, so we can launch multiple processes and let them sleep for a period before they can automatically start. (Timing is in seconds)
from multiprocessing import Process
import os
import random
import time
#store all scripts you want to execute here
eval_scripts = ["script1.test()","script2.test()", "script3.test()"]
#run job on different processes. non-blocking
def run_job(eval_string,time_sleep):
#print out script + time to test
print eval_string + " " + str(time_sleep)
time.sleep(time_sleep) #wait to be executed
#time to start
eval(eval_string)
def do_my_jobs():
start_time = []
#assume the duration between start_time and end_time is 60 mins, leave some time for other jobs after the first job (5-10 mins). This is just to be careful in case random.randrange returns the largest number
#adjust this according to the duration between start_time and end_time since calculating (end_time - star_time) is trivial.
proc1_start_time = random.randrange(60*60 - 10*60)
start_time.append(proc1_start_time)
#randomize timing for other procs != first script
for i in range(len(eval_scripts)-1):
#randomize time from (proc1_start_time + 5 mins) to (end_time - star_time)
start_time.append(random.randint(proc1_start_time+5*60, 60*60))
for i in range(len(eval_scripts)):
p_t = Process(target = run_job, args = (eval_scripts[i],start_time[i],))
p_t.start()
p_t.join()
Now all you need to do is to call do_my_jobs() only ONCE at START_TIME every day.

Categories

Resources