Don't understand this timed while loop attribute error - python

So I have been trying to make a while loop that will run for 10 minutes. But is keeps erroring out on the line with the while loop. It says 'str' object has no attribute 'time'.
I have discovered that if i remove the lines with now.strftime() in them that the code runs but I don't know why it runs without those lines or how to fix it.
I did also try to do something using the datetime module instead of importing the time module but this also fails.
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
time = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass

As #CoryKramer pointed out, you named a variable time, which is also the name of the module you are importing. All I really did was change the time variable to something like currTime. Try the code below (runs for me):
import math
from datetime import datetime
import time
test_num = 1
largest_loop = 0
delay = 60 * 10
end_time = time.time() + delay
def even_number(value):
if value == 2:
return True
def divide_five(value):
if value == 5:
return True
def is_square(value):
if math.sqrt(value).is_integer():
return False
def multiple_of(value):
if value == 2:
return True
def is_happy():
global check
if check == 1:
return True
while time.time() <= end_time:
test_num += 1
check = test_num
now = datetime.now()
loop_counter = 0
record_loop = 6
date = now.strftime("%m/%d/%Y")
currTime = now.strftime("%H:%M:%S")
if even_number(test_num) == True:
if divide_five(test_num) == True:
if is_square(test_num) == True:
for _ in range(record_loop + 4):
loop_counter += 1
if is_happy() == True:
if multiple_of(test_num) == True:
#print(test_num)
record_loop = loop_counter
break
else:
pass
else:
pass
else:
pass
else:
pass
else:
pass
Additionally, consider reading up on:
How to name a module without conflict with variable name?
https://en.wikipedia.org/wiki/Variable_shadowing

dont name your variable in your while loop time when you import the time library:
time = now.strftime("%H:%M:%S")
in your while loop you want to use the time function of the time library but as soon as you run the while loop once it will try to use time() on the string time you defined in the while loop.

I think the problem is here:
time = now.strftime("%H:%M:%S")
Thus, you converted time into a string variable. Name this variable in a different way!
Apart from this, running for 10 minutes at "full throttle" is a lot! Consider to introduce a "sleep" time at the end of the while loop (just suggesting)

Related

Check a condition every 3 minutes without functions and without interrupting the loop

I have this working code that checks a conditions every 3 minutes considering the local time, so every 0, 3, 6, 9.....It prints "checking condition".
import time
def get_next_time():
minute = time.localtime().tm_min
result = 3 - (minute % 3) + minute
if result == 60:
result = 0
return result
next_run = get_next_time()
while True:
now = time.localtime()
if next_run == now.tm_min:
print("checking condition")
#some condition
next_run = get_next_time()
time.sleep(1)
The problem is that I need the code without functions, so I need to find a way to write this code without using any funcion, and I cannot use break or interrput the loop
I tried:
while True:
minute = time.localtime().tm_min
result = 3 - (minute % 3) + minute
if result == 60:
result = 0
now = time.localtime()
if result == now.tm_min:
print("checking conditions")
time.sleep(1)
But it does not work: it does not do nothing.
Any ideas?
you can compact the function in one statement:
import time
next_run = (3 - (time.localtime().tm_min % 3) + time.localtime().tm_min)%60
while True:
now = time.localtime()
if next_run == now.tm_min:
print("checking condition")
#checking conditions...
next_run=(3 - (time.localtime().tm_min % 3) + time.localtime().tm_min)%60
time.sleep(1)
The first time, the get_next_time() will only be executed when next_run == now.tm_min. The second time, you execute it each loop
import time
minute = time.localtime().tm_min
result = 3 - (minute % 3) + minute
if result == 60:
result = 0
while True:
now = time.localtime()
if result == now.tm_min:
print("checking conditions")
minute = time.localtime().tm_min
result = 3 - (minute % 3) + minute
if result == 60:
result = 0
time.sleep(1)
Rounding to the next multiple of 3 minutes contradicts the specification "every 0...".
It is enough to do
import time
first= True
while True:
minute= time.localtime().tm_min
if first or minute == target:
print("checking condition")
first= False
target= (minute + 3) % 60
time.sleep(1)
Update:
I modified the code so that a single call to localtime is made on every iteration, to make fully sure that the minutes do not change between the calls.
More compact but less efficient:
import time
while True:
minute= time.localtime().tm_min
if 'target' not in locals() or minute == target:
print("checking condition")
target= (minute + 3) % 60
time.sleep(1)

Recursive routine escape for backtracking routine

I was wondering if anyone could help me out with this recursive routine for a sudoku back-tracking problem. I was wanting to get out of the recursive routine when the a certain problem had been executing for a known quantity of time, in this case - 2 seconds. However, I am having some trouble getting this to work and believe there may be something wrong with my base case. Any help would be appreciated.
def solver(Domains,SudokuSolv):
start = time.time()
global global_length
global global_row_index
global global_column_index
global global_val_index
global global_number
if global_length == 0:
return True
else:
global_row_index+=3
global_column_index+=3
global_val_index+=3
print(global_row_index)
row = Domains[global_row_index]
col = Domains[global_column_index]
val = global_val_index
for i in Domains[val]:
end = time.time()
if end-start > 2:
global_length = 0
Checker = isValid(i,row,col,SudokuSolv)
if Checker == False:
SudokuSolv[row][col] = i
print(SudokuSolv)
global_length-= 1
if solver(Domains, SudokuSolv):
return True
global_length+=1
SudokuSolv[row][col] = 0
else:
print("Trying next value...")
global_row_index-=3
global_column_index-=3
global_val_index-=3
return False

trying to get an if statement to be triggered during certain times of day

im fairly new with python but im tring to get a device to turn on for one minute and off for 3 minutes repeatedly from the times of 9am to 5pm and i can't get the if statement to reference the updated time from the loop any help would be greatly appreciated!!!
import datetime
import time
n = "on" #to be replaced with GPIO output
f = "off" #to be replaced with GPIO output
nt = "tis not be the time" #used to see if working or not
tt = "tis be time" #used to see if working or not
now = datetime.datetime.now()
hour = now.hour
def count():
now = datetime.datetime.now()
hour = now.second
total = 1
if hour >= 8 and hour <= 16:
now = datetime.datetime.now()
hour = now.hour
for i in range(1,100):
total = total*2
print (tt)
print (n)
time.sleep(60)
print(f)
time.sleep(180)
now = datetime.datetime.now()
hour = now.second
print (hour)
else :
for i in range(1,100):
now = datetime.datetime.now()
hour = now.hour
print (nt)
print (hour)
time.sleep(10)
count()
You could fix it with a while loop instead, it would look like this, just put all of it inside your function
now = datetime.datetime.now()
hour = now.hour
if hour >= 8 and hour <= 16:
run = True
else:
run = False
while run:
total = total*2
print (tt)
print (n)
time.sleep(60)
print(f)
time.sleep(180)
now = datetime.datetime.now()
hour = now.second
print (hour)
if hour >= 8 and hour <= 16:
run = True
else:
run = False
while run == False:
now = datetime.datetime.now()
hour = now.hour
print (nt)
print (hour)
time.sleep(10)
if hour >= 8 and hour <= 16:
run = True
else:
run = False
Maybe using a while statement. In addition, you have hour = now.second on the second line of the function count and I think it should be hour = now.hour.
See the code with comments:
import datetime
import time
n = "on" #to be replaced with GPIO output
f = "off" #to be replaced with GPIO output
nt = "tis not be the time" #used to see if working or not
tt = "tis be time" #used to see if working or not
#Next lines are redundant, commented out.
#now = datetime.datetime.now()
#hour = now.hour
def count():
now = datetime.datetime.now()
hour = now.hour #now.second
total = 1
while hour >= 8 and hour <= 16:
now = datetime.datetime.now()
hour = now.hour
# for i in range(1,100): -> why you need this?
total = total*2
print (tt)
print (n)
time.sleep(60)
print(f)
time.sleep(180)
now = datetime.datetime.now()
hour = now.hour #now.second
print (hour)
for i in range(1,100): #I don't know why you need a loop here
now = datetime.datetime.now()
hour = now.hour
print (nt)
print (hour)
time.sleep(10)
count()
Edited for correcting another hour = now.second inside the while loop
I don't know how are you planning on running the code, but the main problem I see is that you do not have any loop for your code to run infinitely and check the time condition.
Also it's not clear for me why you need this total variable that gets doubled.
Another thing is your for loops - the condition is not clear. Why do you want to run it in this specific range?
What I would do is I would create an infinite loop and inside it make some decisions based on a clear time conditions - the conditions that are specified by you.
So if I understood your case correctly I'd rather write something like this:
# between 9am to 5pm turn on the device for 60 seconds and off for 180 seconds repeatedly
from datetime import datetime
import time
def update_device_state(state):
# TODO: implement GPIO output code
pass
def run():
device_state = 'off'
new_state = device_state
on_timer = 0
off_timer = time.time() - 180 # initial value must be over 180 seconds to trigger device on a first run
while True:
hour = datetime.now().hour
if 5 <= hour <= 17:
if device_state == 'off' and time.time() - off_timer > 180:
on_timer = time.time()
new_state = 'on'
off_timer = 0
elif device_state == 'on' and time.time() - on_timer > 60:
off_timer = time.time()
new_state = 'off'
on_timer = 0
else:
if device_state = 'on'
new_state = 'off'
on_timer = 0
off_timer = time.time()
if device_state != new_state:
update_device_state(new_state)
device_state = new_state
time.sleep(1)
run()
But the code requires some testing as I just quickly drafted it and I just briefly red it.

for-loop with a timeout inside the loop?

I'm trying to find a way to do a for loop, and if the iteration of the for loop is more than the timeout, then it break and go to the next iteration.
Example :
timeout = 60
for i in mylist:
i += 1
if time > timeout:
break
I think you can use the time module as shown here:
import time
#get the time at the start of the program
x = time.localtime(time.time())
start_time = time.strftime('%S', x)
#the loop
timeout = 5
for i in range(10000000):
i += 1
y = time.localtime(time.time())
now_time = time.strftime('%S', y)
run_time = int(now_time) - int(start_time)
print(run_time) #to see the run_time
if run_time > timeout:
break
Assuming that a single iteration doesn't take so much, just use time module and a while loop as follows:
mylist = [1,2,3]
import time
timeout = 60
time_start = time.time()
i = 0
while i < len(mylist) and time.time() - time_start < timeout:
# do your stuff
i += 1
if i == len(mylist):
# this code runs if the iteration has completed, pass does nothing
pass
else:
# and this code runs if there was a timeout
pass

Start and pause a process in python

I have a function that calculates the Fibonacci numbers. I am trying to add a feature that sends a signal indicating that I need to pause the function running. Once I get the signal, I store away all the numbers calculated thus far.
And when the user wants to resume the function, I can load back the files and start calculating from where we had stopped.
This is the code I have
MAX = 100000
fibo_series = [0] * MAX
import pickle
def fib(start_value=0, stop_value=1000, stop_signal=False):
if not stop_signal:
for i in range(start_value, stop_value):
if i == 0:
fibo_series[i] = 0
elif i == 1 or i == 2:
fibo_series[i] = 1
else:
fibo_series[i] = fibo_series[i-1] + fibo_series[i-2]
return fibo_series[i]
else:
with open('fibo_series.pkl', 'wb') as f:
pickle.dump(fibo_series, f)
def reload_fib():
with open('fibo_series.pkl', 'rb') as f:
fibo_series = pickle.load(f)
start_value = fibo_series[1:].index(0) + 1
stop_value = len(fibo_series)
return fib(start_value, stop_value, stop_signal=False)
The part that I am not able to figure out is how to use this stop_signal once the function has started running. Once the function has started the value stop_signal is locked. The only way I know to pause a function is by terminating it which is not what I am trying to do.
How do I achieve this?
I am not sure what are the stop and run conditions, but a simple work around is to use a global variable for these two functions. This is not better than using a lock of a thread library but if your work is simply to use one process and does not need complexity, then you may try.
import threading
import time
MAX = 100000
fibo_series = [0] * MAX
import pickle
stop_signal = False
def fib(start_value=0, stop_value=1000):
for i in range(start_value, stop_value):
if (not stop_signal):
print('here', i)
time.sleep(1)
if i == 0:
fibo_series[i] = 0
elif i == 1 or i == 2:
fibo_series[i] = 1
else:
fibo_series[i] = fibo_series[i-1] + fibo_series[i-2]
else:
break
return fibo_series[i]
print('exiting... stop_signal: ', stop_signal)
with open('fibo_series.pkl', 'wb') as f:
pickle.dump(fibo_series, f)
def reload_fib():
with open('fibo_series.pkl', 'rb') as f:
fibo_series = pickle.load(f)
start_value = fibo_series[1:].index(0) + 1
stop_value = len(fibo_series)
global stop_signal
stop_signal = False
return fib(start_value, stop_value)
x = threading.Thread(target=fib )
x.start()
time.sleep(10)
stop_signal = True
print('finished...')
Then, whenever the user wants to stop the execution, you can set the global variable stop_signal=True
and the output is:
here 0
here 1
here 2
here 3
here 4
here 5
here 6
here 7
here 8
here 9
finished...
I hope this helps.

Categories

Resources