Script B slows down script A - python

I am working with Python 2.7 on a Raspberry Pi.
I run a script A which is a for-loop, taking pictures every 30 seconds. Normally, for each iteration, it takes about 5 seconds to capture the scene and save it, and then it sleeps (for about 25 seconds) until the next iteration.
After some time I run a script B which is calculating stuff based on the images taken by script A. So the two scripts are running at the same time. I am not using subprocess or anything, just executing the two scripts separately.
My problem is : when script B is running, script A is slowed down a lot, so that sometimes the first 5 seconds turn into 25-30 seconds and then one iteration can last 40 seconds or more !
Do you know why durations are not respected in script A, and how I can solve this issue ?
Thanks :) !

I believe if you are in a Linux environment you can use nice command in order to balance the cpu usage.for example :
nice --12 script.py
the number above represents the amount of being nice to cpu.it is between -20 and +19.

If the calculation amount of "script B" is nearly always the same you could subtract this time in seconds from the sleep timer.
2.You also could take the runtime in seconds of the scripts, that you will output at the end of their execution. The problem is the python programm will wait for a finished script before continuing.
import subprocess
import time
counter = 0
script_a_runtime = 0
script_b_runtime = 0
while True:
counter += 1
script_a = 0
script_b = 0
script_a_runtime = int(subprocess.check_output(['scripta']))
if counter >=5:
counter = 0
script_b_runtime = int(subprocess.check_output(['scriptb']))
sleeptime = 30 - script_a_runtime - script_b_runtime
if sleeptime:
time.sleep(sleeptime)
3.Timers
import datetime
import time
import subprocess
script_a_runtime = 0
script_b_runtime = 0
while True:
counter += 1
start_a = datetime.datetime.now()
subprocess.check_output(['script_a'])
finish_a = datetime.datetime.now()
script_a_runtime = finish_a - start_a
if counter >= 5:
counter = 0
start_b = datetime.datetime.now()
subprocess.check_output(['script_b'])
finish_b = datetime.datetime.now()
script_b_runtime = finish_b - start_b
sleeptime = 30 - script_a_runtime.seconds - script_b_runtime.seconds
if sleeptime:
time.sleep(sleeptime)
I dont think its a good idea to run those scripts that depend on each other side by side. Also if scriptA/B is not finished before it should be run again there may arise problems.

Related

Change the Scheduling Time - Python

I am using schedule module to automatically run a function...
I am thinking of changing the scheduling time dynamically, but the solution is not success
Code -
import schedule
import pandas
from time import gmtime, strftime, sleep
import time
import random
time = 0.1
def a():
global time
print(strftime("%Y-%m-%d %H:%M:%S", gmtime()))
index = random.randint(1, 9)
print(index, time)
if(index==2):
time = 1
print(strftime("%Y-%m-%d %H:%M:%S", gmtime()))
schedule.every(time).minutes.do(a) #specify the minutes to automatically run the api
while True:
schedule.run_pending()
In this program, I scheduled the program to run every 6 seconds. And if the random integer - index value becomes 2, then the time variable is assigned as 1(1 minute). I checked, the time variable is changed to 1 after the random integer index becomes 2. The issue - After changing the time variable to 1, the scheduling still runs the function a() every 6 seconds not 1 minute.
How to change the scheduling time dynamically?
Thank you
After changing the time variable to 1, the scheduling still runs the function a() every 6 seconds not 1 minute.
This is because schedule.every(time).minutes.do(a) # specify the minutes to automatically run the api sets time to 6 seconds at beginning which does not change even if you change the value of that variable because that line has executed just once where value of time was 6 seconds at that execution.
How to change the scheduling time dynamically?
After reading DOCUMENTATION, I found nothing(I think) regarding changing time manually(when certain condition becomes satisfies) but it has built in Random Interval function where that function itself specifies random time within the range.
In your case you could do:
schedule.every(5).to(10).seconds.do(a)
The problem is that you cannot change time when certain condition satisfies.
Maybe there might be some way to fix that issue but could not figure out. And these information may help to investigate further to solve your problem.
I usually use custom schedulers, as they allow greater control and are also less memory intensive. The variable "time" needs to be shared between processes. This is where Manager().Namespace() comes to rescue. It talks 'between' processes.
import time
import random
from multiprocessing import Process, Manager
ns = Manager().Namespace()
ns.time = 0.1
processes = []
def a():
print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()))
index = random.randint(1, 4)
if(index==2):
ns.time = 1
print(index, ns.time)
while True:
try:
s = time.time() + ns.time*60
for x in processes:
if not x.is_alive():
x.join()
processes.remove(x)
print('Sleeping :',round(s - time.time()))
time.sleep(round(s - time.time()))
p = Process(target = a)
p.start()
processes.append(p)
except:
print('Killing all to prevent orphaning ...')
[p.terminate() for p in processes]
[processes.remove(p) for p in processes]
break

How to run a python script that executes every 5 minutes BUT in the meantime executes some other script

I don't want the code to go the sleep in these 5 minutes and just waits. I want to run some other code block or script in the meantime.
How to run a python script that executes every 5 minutes BUT in the meantime executes some other script it code block until the 5 minute time is reached again.
e.g I want to run 3 functions . One to run every 5 minutes. another every 1 minutes. another every 10-20 seconds.
You can use a Thread to control your subprocess and eventually kill it after 5 minutes
import time
delay = 1 # time between your next script execution
wait = delay
t1 = time.time()
while True:
t2 = time.time() - t1
if t2 >= wait:
wait += delay
# execute your script once every 5 minutes (now it is set to 1 second)
# execute your other code here
First, you need to get the time of your script, then you need a variable to store "wait time" of your script (in this case "wait").
Every time your script time is higher or equal to "wait" delay variable is added to wait and code is executed.
And for multiple delays it's:
import time
delay = [1, 3]
wait = [delay[0], delay[1]]
t1 = time.time()
while True:
t2 = time.time() - t1
for i in range(len(wait)):
if t2 >= wait[i]:
wait[i] += delay[i]
if i==0:
print("This is executed every second")
if i==1:
print("This is executed every 3 second")

How to Run Python Code 30 Sec before Every 5th Minute

I have a python program which I want to execute exactly 30 seconds before every 5th Minute and need to run for 30 seconds only.
Rather than looping and testing if it's the right time over and over again, it's better to calculate the amount of time needed to wait, and sleep until then so the processor can go off and do other things. To do this we still use the datetime module and just a bit of simple math.
from datetime import datetime as dt
from time import sleep
#Calculating sleep interval
t = dt.now()
#seconds in the hour
sec = t.second + t.minute*60
#seconds since the last 5 min interval
sec = sec % 300
#until the next 5 min interval
sec = 300 - sec
#30 sec before that
sec = sec - 30
#if negative we're within 30 sec of 5 minute interval so goto next one
if sec < 0:
sec = sec + 300
sleep(sec)
while True: #loop forever
#with a little re-arranging and boolean math, this can all be condensed to:
t = dt.now()
s = (t.second + 60*t.minute) % 300
sleep(270 - s + 300 * (s >= 270))
#yourFunction()
For very simple cases this should work. If at any point your program crashes, or if the computer re-boots, or a myriad of other reasons, It would be better to use something built in to the OS which will re-start the program automatically, and can handle other conditions such as setting sleep timers, or only executing if a particular user is logged in. On Windows this is task scheduler, on Linux this is typically cron, and OSX is launchd (at least according to developer.apple.com)
If you're running this code indefintley, I'd suggest you look at following Aaron's adivce at look at superuser.com, apple.stackexchange.com or askubuntu.com.
However, if you were going to write this in Python, you could use the datetime module and find the time that's elapsed.
from datetime import datetime
import time
def your_function(t1):
i = 0
# For the next 30 seconds, run your function
while (datetime.now() - t1).seconds =< 30:
i += 1
print(i)
time.sleep(1)
# Run indefintely
while True:
# Record the current time
t1 = datetime.now()
while t1:
# Find the elapsed time in seconds
# If the difference is 270 seconds (4 minutes and 30 seconds)
if (datetime.now()-t1).seconds == 270:
your_function(t1)
# Remove t1 and start at the top of the loop again
t1 = None

Pygame simple score system

I have created a simple score system for my pygame. but it's pausing the game. I know it's because of time.sleep but I don't how to sort it out.
The score system is to +100 every 5 seconds while start is true, code:
while start == True:
time.sleep(5)
score = score + 100
Full code with indentation: http://pastebin.com/QLd3YTdJ
code at line : 156-158
Thank you
Instead of using sleep, which stalls the game until time has elapsed, you want to count up an internal timer with the number of seconds which have passed. When you hit 5 seconds, increment the score and then reset the timer.
Something like this:
scoreIncrementTimer = 0
lastFrameTicks = pygame.time.get_ticks()
while start == True:
thisFrameTicks = pygame.time.get_ticks()
ticksSinceLastFrame = thisFrameTicks - lastFrameTicks
lastFrameTicks = thisFrameTicks
scoreIncrementTimer = scoreIncrementTimer + ticksSinceLastFrame
if scoreIncrementTimer > 5000:
score = score + 100
scoreIncrementTimer = 0
This could easily be improved (what if your frame rate is so low there's more than 5 seconds between frames?) but is the general idea. This is commonly called a "delta time" game timer implementation.
If i understand you correctly you dont want the while True: score += 100 loop to block your entire program?
You should solve it by moving the score adding to a seperate function
and use the intervalfunction of APScheduler http://packages.python.org/APScheduler/intervalschedule.html
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
# Schedule job_function to be called every 5 seconds
#sched.interval_schedule(seconds=5)
def incr_score():
score += 100
This will result in APScheduler creating a thread for you running the function every 5 seconds.
you might need to do some changes to the function to make it work but it should get you started at least :).

With python: intervals at x:00 repeat

How do I sched a repeat timer for 5 min intervals. Which fire at 00 seconds, then repeat at 00. Ok, not hard real-time but as close as possible with sys lags. Trying to avoid a build up in lags and get near 00.
Lang: Python, OS: WinXP x64
System has 25ms resolution.
Any code would be helpful, tia
I don't know how to do it any more accurately than with threading.Timer. It's "one-shot", but that just means the function you schedule that way must immediately re-schedule itself for another 300 seconds later, first thing. (You can add accuracy by measuring the exact time with time.time each time and varying the next scheduling delay accordingly).
Try and compare the time printouts of these two code samples:
Code Sample 1
import time
delay = 5
while True:
now = time.time()
print time.strftime("%H:%M:%S", time.localtime(now))
# As you will observe, this will take about 2 seconds,
# making the loop iterate every 5 + 2 seconds or so.
## repeat 5000 times
for i in range(5000):
sum(range(10000))
# This will sleep for 5 more seconds
time.sleep(delay)
Code Sample 2
import time
delay = 5
while True:
now = time.time()
print time.strftime("%H:%M:%S", time.localtime(now))
# As you will observe, this will take about 2 seconds,
# but the loop will iterate every 5 seconds because code
# execution time was accounted for.
## repeat 5000 times
for i in range(5000):
sum(range(10000))
# This will sleep for as long as it takes to get to the
# next 5-second mark
time.sleep(delay - (time.time() - now))

Categories