Python - How to Increment A Value As Time Passes [duplicate] - python

This question already has answers here:
How to create a python loop that allows other code to run as well
(3 answers)
Closed 1 year ago.
I'm trying to do something simple here, i want to increase my cost variable which is (100.00) by .01 every 5 minutes, so after every 5 minutes my new value/variable should be, 100.01, then 100.02, then 100.03 and so on..
but i can't figure out how to add it to my existing value.
Here is what i've tried so far, i've reduced the 300 seconds to 10 seconds to speed things up.
import time
import datetime
tracking = time.time()
def values():
global tracking
now = datetime.datetime.now()
cost = 100.00
increase = .01
newvalue = []
for x in range(1,1000):
print(x)
time.sleep(2)
if time.time() - 10 > tracking:
newvalue.append(float(increase))
print(newvalue)
print(now)
tracking = time.time()
values()
any help appreciated.

It seems like you want the += operator. This adds the right-hand value to the value to the value stored in the left-hand variable.
import time
import datetime
tracking = time.time()
def values():
global tracking
now = datetime.datetime.now()
cost = 100.00
increase = .01
for x in range(1,1000):
print(x)
time.sleep(2)
if time.time() - 10 > tracking:
cost += increase
print('Cost: {}'.format(cost))
print(now)
tracking = time.time()
values()
There are other issues to consider:
Floats are not a good way to store currency values. Because they store binary fractions, they cannot represent all decimal fractions. Consider using decimal.Decimal instead.
To track elapsed time, it's best to use time.monotonic. datetime.now() can be adjusted externally (e.g. by ntpdate), so you cannot assume a change in datetime.now represents elapsed time.
There doesn't seem to be a need to store tracking as a global.
In a single-threaded program, values will not exit until 1000 is reached, which means you can't have other program logic running while the cost is incrementing. Calculating the cost on-demand (as others have suggested) will allow you to run other program logic instead of just looping.

Try this
import time
def increase_value_evrey_t_sec(initail_value, interval, increase_by,stop_after = -1):
counter = 0
values = []
while counter < stop_after or stop_after == -1:
time.sleep(interval)
initail_value += increase_by
print(initail_value)
values.append(initail_value)
counter += 1
increase_value_evrey_t_sec(2,2,3,4)
increase_value_evrey_t_sec(2,2,3,4)

Related

I'm trying to make a program that makes you lose "energy" (Python 3) [duplicate]

This question already has answers here:
How to create a python loop that allows other code to run as well
(3 answers)
How do I get input at the same time while constantly increasing a value in python?
(1 answer)
Closed 1 year ago.
I'm trying to make a program that makes you lose "energy" for a game.
I made it so when you press enter you gain "energy":
if question == '':
print("press enter to gain energy")
while True:
energyup = input()
if energyup == "":
energy += energygain
print(energy)
I also want to make it so you lose energy every 0.5 seconds. I don't know how to do this.
I tried adding:
while True:
energy -= energyloss
print(energy)
time.sleep(1)
to the bottom of the program, but that makes you lose energy WAY too fast and I don't know if there is a way to make 1 line of code sleep while everything else continues (I'm using time.sleep which affects the whole program) and on top of that it makes the energy gaining system just not work.
Sorry if this is a dumb question I just started learning programing and this is my first question on this site.
Instead of time.sleep, just check if it has been 0.5 seconds past the last time energy was lost:
prev_time = time.time()
while True:
# rest of the game loop
curr_time = time.time()
if curr_time - prev_time > 0.5:
energy -= energyloss
prev_time = curr_time
This lets the rest of the game loop code to run concurrently.
You need to use threads. Thread A is responsible for consumption, and thread B listens for input
energy = 0
energyloss = 1
energygain = 1
lock = threading.Lock()
def consumption():
global energy
while 1:
with lock:
energy -= energyloss
time.sleep(0.5)
print(energy)
threading.Thread(target=consumption).start()
Use threading.Lock to ensure thread safety
You also need to call with lock when increasing energy
I see solution with threading which might be helpful but from your problem statement, I believe you only need to have a function that will provide the diff between the total energy accumulated and the one lost with time.
To do so, you may start a timer at the beginning and create a function that will use the current time minus the execution time to calculate the energy lost each time.
The below might be enough for you case:
import time
energy_gain_constant = 5
energy_loss_constant = -2
total_energy_gain = 0
start_time = time.time()
def print_total_energy():
print(total_energy_gain + int((time.time() - start_time) / 0.5) * energy_loss_constant)
print("press enter to gain energy")
while True:
energyup = input()
if energyup == "":
total_energy_gain += energy_gain_constant
print_total_energy()
Adding debug logs into the method that prints how it will behave:
def print_total_energy():
total_energy_lost = int((time.time() - start_time) / 0.5) * energy_loss_constant
print(f'Total execution time: {time.time() - start_time}')
print(f'Total energy lost: {total_energy_lost}')
print(f'Total energy gained: {total_energy_gain}')
print(f'Total Energy: {total_energy_gain + total_energy_lost}')
Output:
Total execution time: 12.982820272445679
Total energy lost: -50
Total energy gained: 65
Total Energy: 15

How to make a timer more efficient

I am quite new to coding and i am wondering how to make it more efficient. I am running it on a raspberry pi which will have other tasks so i want this to be as easy to run as possible. The code will use a magnetic sensor to record passes made by a magnet mounted on a wheel and from there determine the speed of the outside diameter of the wheel. It would be useful to implement something that takes the five last speed outputs and gives sort of an average but only if it does not affect the complexity of the code much. Would be really greatful for any help!
from gpiozero import Button
import time
global t0
t0 = time.clock()
raduis = 300
button = Button (21)
from signal import pause
def calculate_speed(radius):
global t0
t1 = time.clock
interval = t1 - t0
speed = radius/interval
print (speed, 'mm/sek')
y = True
while y == True:
button.when_pressed = calculate_speed(radius)
time.sleep(0.2)
#used to prevent one pass of the magnet from recording many passes
You should store five last speed outputs in an array (list) and then you can calculate the average speed
speed_records = []
def calculate_speed(radius):
global t0
t1 = time.clock
interval = t1 - t0
speed = radius/interval
print (speed, 'mm/sek')
speed_records.append(speed) # Adds one speed record to the list
if len(speed_records) >= 5: # checks if there are 5 five records available
last_five_records = speed_records[-5:] # Seperates five last records
average = sum(last_five_records) / 5
print('Average Speed:',average) # Prints out the average
if len(speed_records) > 10: # Free Up some memory
speed_records = list(set(speed_records) - set(speed_records[:5])) #removes the first five records
The following code uses modular arithmetic to iterate through a single list, adding and overwriting values, and printing the averaged speed. Adjust iterations to control how many passes to average over.
from gpiozero import Button
from signal import pause
import time
radius = 300
button = Button (21)
iterations = 5
speeds = [0] * iterations
speed_idx = 0
def calculate_speed(radius):
global speeds, speed_idx
t1 = time.time()
speeds[speed_idx] = radius / (t1- t0)
print (sum(speeds) / iterations, 'mm/sek')
speed_idx += 1
speed_idx %= iterations
t0 = time.time()
while True:
button.when_pressed = calculate_speed(radius)
time.sleep(0.2)
t0 = time.time()
Note this takes 5 measurements to "ramp up" in a sense. If you want- you could add an if statement to avoid printing out the first 4 recordings.
Additionally, if you wanted a smoother measurement of speeds, it occurred to me that you could use a single value to hold the sum of the speeds of the last N passes, and each time subtract off the average (assuming N sums), and add the new speed. It would a few extra passes to stabilize, but afterwards it should smooth the reported speeds a bit.

How to run a search that returns after a certain amount of time?

I have a function that runs an iterative deepening search and would like to return the value from the deepest search after a certain amount of time has passed. The code skeleton would look something like
import time
answers = []
START = time.clock()
current_depth = 1
while time.clock() - START < DESIRED_RUN_TIME:
answers.append(IDS(depth=current_depth))
current_depth += 1
return answers[-1]
The problem with this code is it will not return until after the time limit has passed. What is the best way to solve this? If I should just add time checks in the IDS function, how can I make sure to return the last value found? Any help would be greatly appreciated.
Your code should work unless IDS is blocking and takes a very long time. Then you have to wait until IDS is finished and the time limit may not be all that precise.
I'm not sure exactly what you mean by
would like to return the value from the deepest search after a certain amount of time has passed.
and
The problem with this code is it will not return until after the time limit has passed.
If you have time limits and you have update times then you can use this code as a generator.
import time
answers = []
START = time.clock()
current_depth = 1
def get_ids(update_time, limit_time):
last_update = time.clock()
while time.clock() - START < DESIRED_RUN_TIME:
answers.append(IDS(depth=current_depth))
current_depth += 1
if time.clock() - last_update < update_time:
last_update = time.clock()
yield answers[-1]
yield answers[-1]
for i in get_ids(1, 10): # get an ids every second and stop after 10 seconds
print(i)

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)

Python - Print index of for loop only once every five minutes

I'm trying to get a for loop to print the value of 'i' every 5 minutes
import threading
def f(i):
print(i)
threading.Timer(600, f).start()
for i in range(1,1000000000000):
f(i=i)
However, this method results in the code printing the value of i instantly since it calls 'f' as soon as it finds 'i'.
I know this is not the first time someone will ask, nor the last, but I can't get it to work on a for loop nested within a function.
I'm fairly new to Python and I'd appreciate any help.
How about just keeping track of how long has passed in the loop?
from timeit import default_timer as timer
start = timer()
freq = 5 * 60 # Time in seconds
last_time = 0.0
for i in range(int(1e8)):
ctime = timer()
if ctime - last_time > freq:
print(i)
last_time = ctime
I imagine you can make this more efficient by only checking the time every N iterations rather than every time. You may also want to look into using progressbar2 for a ready-made solution.
I prefer using datetime, as I think it's more intuitive and looks a bit cleaner. Otherwise, using more or less the same approach as Paul:
from datetime import datetime, timedelta
print_interval = timedelta(minutes=5)
# Initialize the next print time. Using now() will print the first
# iteration and then every interval. To avoid printing the first
# time, just add print_interval here (i.e. uncomment).
next_print = datetime.now() # + print_interval
for i in range(int(1e8)):
now = datetime.now()
if now >= next_print:
next_print = now + print_interval
print(i)
Also note that before python 3.x xrange would be preferable over range.

Categories

Resources