creating a system that 'unlocks' when the timer reaches 0 - python-3.x

I'm working on a script where there is this timer and a user enters a duration e.g 2days: 2hoursd : 2minutes: 2seconds and when the timer hits 0 the word "unlocked" appears
I am absolutely lost and have no clue where to begin
ide show some code but I'm honestly lost
the user enters a duration
timer ticks down
timer reaches 0
word "unlocked" appears

The start_timer function starts a blocking timer which sleeps for one second each, until the defined duration has been reached. Additionally, if you run the script as main, it asks for user input to set the timer.
import datetime
import time
def start_timer(days=0, hours=0, minutes=0, seconds=5):
t0 = datetime.datetime.now()
delta = datetime.timedelta(days=days, seconds=seconds, minutes=minutes,
hours=hours)
t1 = datetime.datetime.now()
while (t1 - t0) < delta:
time.sleep(1)
t1 = datetime.datetime.now()
print("Unlocked")
if __name__ == "__main__":
days = float(input("Days? "))
hours = float(input("Hours? "))
minutes = float(input("Minutes? "))
seconds = float(input("Seconds? "))
start_timer(days=days, hours=hours, minutes=minutes, seconds=seconds)

Related

Groovy not converting seconds to hours properly

I have an integer that is:
19045800
I tried different code:
def c = Calendar.instance
c.clear()
c.set(Calendar.SECOND, 19045800)
echo c.format('HH:mm:ss').toString()
String timestamp = new GregorianCalendar( 0, 0, 0, 0, 0, 19045800, 0 ).time.format( 'HH:mm:ss' )
echo timestamp
Both return 10:30:00
19045800 seconds is supposed to be over 5000 hours. What am I doing wrong?
I'm not sure what you are looking for. But if your requirement is to calculate the number of hours, minutes, and the remainder of seconds for given seconds following code will work.
def timeInSeconds = 19045800
int hours = timeInSeconds/3600
int minutes = (timeInSeconds%3600)/60
int seconds = ((timeInSeconds%3600)%60)
println("Hours: " + hours)
println("Minutes: " + minutes)
println("Seconds: " + seconds)
You're attempting to use a Calendar, but what you're actually discussing is what Java calls a Duration – a length of time in a particular measurement unit.
import java.time.*
def dur = Duration.ofSeconds(19045800)
def hours = dur.toHours()
def minutes = dur.minusHours(hours).toMinutes()
def seconds = dur.minusHours(hours).minusMinutes(minutes).toSeconds()
println "hours = ${hours}"
println "minutes = ${minutes}"
println "seconds = ${seconds}"
prints:
hours = 5290
minutes = 30
seconds = 0

How to synchronize (make threadsafe) all instances of a Class in Python? (Ideally implemented in superclass)

I'm fairly new to threading, and I am trying to adapt some code to make it threadsafe.
My problem is that multiple threads access multiple methods of a single instance at the same time. Because the methods both use and change the instances state, bad things obviously happen...
I want each instance to be accessed by only 1 thread at a time (i.e. only one method of that instance running at any time and any other threads should wait).
As a note, the threads are spawned from a Dash app, so I include that keyword in case others end up here, but I don't think it makes a difference to the problem overall.
I'll start with a very simple case and then add in the complexity that I want to achieve (although it may not affect the solution).
Simple Case
Let's say I have a class like this:
class BaseClass:
pass
class Simple(BaseClass):
def __init__(self, a=1):
self.a = a
self.b = None
def print(self):
print(f'a = {self.a}, b = {self.b}')
time.sleep(1)
self.b = 'b_set'
I want to be able to run the following tests:
if __name__ == '__main__':
test1 = Simple(a=1)
test2 = Simple(a=2)
t1 = threading.Thread(target=test1.print)
t2 = threading.Thread(target=test2.print)
t3 = threading.Thread(target=test1.print) # Another call to test1.print
threads = (t1, t2, t3)
print('Starting all threads')
start_time = time.time()
for t in threads:
t.start()
for t in threads:
t.join()
print(f'Aiming for 2s of execution, took {time.time()-start_time:.1f}s')
I am aiming to see this output:
Starting all threads
a = 1, b = None
a = 2, b = None
a = 1, b = b_set
Aiming for 2s of execution, took 2.0s
but what I actually see is:
Starting all threads
a = 1, b = None
a = 2, b = None
a = 1, b = None
Aiming for 2s of execution, took 1.0s
Where crucially the execution time SHOULD be 2.0s (where it is currently 1.0s) because I want t1 and t2 to run concurrently and then I want t3 to run (i.e. t3 should not be running at the same time as t1).
I want to modify BaseClass so that this works.
I found this (Synchronizing All Methods in an Object) which I believe is a solution, however, it is written for Python 2, and I believe there is a much cleaner solution possible in Python 3 based on this (How to synchronize all methods in class python3?).
The second solution is very close, it does make the Simple class threadsafe, but it also prevents t1 and t2 from running at the same time because it applies to the whole subclass, not the instances of the subclass. I don't understand the ins and outs of __init_subclass__ well enough to know how to modify this behaviour in a nice way.
Any help would be greatly appreciated!
More complex examples to further illustrate intention and more difficult cases
class BaseClass(abc.ABC):
def __init__(self, a=1):
self.a = a
def print(self):
print(f'a = {self.a}')
time.sleep(1)
def print_get(self):
print(f'get_a = {self.get_a()}')
time.sleep(1)
def get_a(self):
"""An example of some methods having to call other methods of self"""
return self.a
#abc.abstractmethod
def reentrant_print(self, i=0):
"""Something which has to reenter itself (or other methods of self)"""
pass
class SubClass(BaseClass):
def reentrant_print(self, i=0):
"""Should print three times in a row"""
print(f'a = {self.a}: i = {i}\n')
time.sleep(0.5)
if i < 3:
self.reentrant_print(i+1)
if __name__ == '__main__':
test1 = SubClass(a=1)
test2 = SubClass(a=2)
methods = ('print', 'print_get', 'reentrant_print')
for method in methods:
print(f'\n\nStarting tests for method = {method}')
t1 = threading.Thread(target=getattr(test1, method))
t2 = threading.Thread(target=getattr(test2, method))
t3 = threading.Thread(target=getattr(test1, method)) # Another call to test1
t4 = threading.Thread(target=test1.print) # Another call to test1 on a different method
threads = (t1, t2, t3, t4)
print('Starting all threads')
start_time = time.time()
for t in threads:
t.start()
for t in threads:
t.join()
print(f'All threads finished in {time.time()-start_time:.1f}s')
Aiming for Output to be something like:
Starting tests for method = print
Starting all threads
a = 1
a = 2
a = 1
a = 1
All threads finished in 3.0s <<<<< Note: Should be 3.0s because it should run t1 and t2, then t3, then t4
Starting tests for method = print_get
Starting all threads
get_a = 1
get_a = 2
get_a = 1
a = 1
All threads finished in 3.0s <<<<< Note: Should be 3.0s because it should run t1 and t2, then t3, then t4 (or could allow t4 to run at same time as t1 and t2)
Starting tests for method = reentrant_print
Starting all threads
a = 1: i = 0
a = 2: i = 0
a = 1: i = 1
a = 2: i = 1
a = 1: i = 2
a = 2: i = 2
a = 1: i = 3
a = 2: i = 3
a = 1: i = 0 <<< Note: From ~here it should be only t3 running
a = 1: i = 1
a = 1: i = 2
a = 1: i = 3
All threads finished in 4.0s <<<<< Note: Should be 4.0s because it should run t1 and t2, then t3, then t4
Even just shedding some light on the Simple Case would be very helpful, although I include the more complex cases in case it is easy to extend behaviour if you know what you're doing!

How to create a watchdog on a program in python?

I want to know is it even possible to create a watchdog on a program,
I am trying to do Discrete event simulation to simulate a functioning machine,
the problem is, once I inspect my machine at let's say time = 12 (inspection duration is 2 hours lets say) if the event failure is at 13-time units) there is no way that it can be because I am "busy inspecting"
so is there a sort of "watchdog" to constantly test if the value of a variable reached a certain limit to stop doing what the program is doing,
Here is my inspection program
def machine_inspection(tt, R, Dpmi, Dinv, FA, TRF0, Tswitch, Trfn):
End = 0
TPM = 0
logging.debug(' cycle time %f' % tt)
TRF0 = TRF0 - Dinv
Tswitch = Tswitch - Dinv
Trfn = Trfn - Dinv
if R == 0:
if falsealarm == 1:
FA += 1
else:
tt = tt + Dpmi
TPM = 1
End = 1
return (tt, End, R, TPM, FA, TRF0, Trfn, Tswitch)
Thank you very much!
basically you can't be inspecting during x time if tt + x will be superior to the time to failure TRF0 or Trfn

What is the impact of a function on execution speed?

Fairly new to python and working on an application where speed is critical - essentially in a race to book reservations online as close to 7AM as possible. Was trying to understand the impact on execution speed that a function call has, so i developed a very simple test: count to 1,000,000 and time start and end using both in line and a called function. However, the result i get says that the function takes about 56% of the time that the inline code takes. I must be really be missing something. Can anyone explain this please.
Code:
import time
def timeit():
temp = 0
while temp < 10000000:
temp += 1
return
time1 = time.time()
temp = 0
while temp < 10000000:
temp += 1
time2 = time.time()
timeit()
time3 = time.time()
temp = 0
while temp < 10000000:
temp += 1
time4 = time.time()
timeit()
time5 = time.time()
print("direct took " + "{:.16f}".format(time2 - time1) + " seconds")
print("indirect took " + "{:.16f}".format(time3 - time2) + " seconds")
print("2nd direct took " + "{:.16f}".format(time4 - time3) + " seconds")
print("2nd indirect took " + "{:.16f}".format(time5 - time4) + " seconds")
results:
direct took 1.6094279289245605 seconds
indirect took 0.9220039844512939 seconds
2nd direct took 1.5781939029693604 seconds
2nd indirect took 0.9375154972076416 seconds
I apologize for missing something silly that i must have done?

Python 3: How to exit loop without stopping function

I am a complete newbie and have tried solving this problem (with my own head and with online research) for the last 5 hours.
Below is a snippet of a function we have written to simulate a game. We want to offer the ooportunity to start a new round - meaning if a player hits "b", the game should start again at the beginning of the range (0, players). But right now it just goes onto the next player in the range (if player 1 enters "b", the program calls player 2)
players = input(4)
if players in range(3, 9):
for player in range(0, players):
sum_points = 0
throw_per_player_counter = 0
print("\nIt is player no.", player+1, "'s turn!\n")
print("\nPress 'return' to roll the dice.\n"
"To start a new round press 'b'.\n"
"Player", player+1)
roll_dice = input(">>> ")
if roll_dice == "b":
player = 0
throw_per_player_counter = 0
sum_points = 0
print("\n * A new round was started. * \n")
I have tried return and break, also tried to put it all in another while-loop... failed. Break and return just ended the function.
Any hints highly appreciated!
you could change the for loop to a while loop. instead of using a range, make player a counter
players = 4
if 3 <= players < 9:
player = 0 # here's where you make your counter
while player < players:
sum_points = 0
throw_per_player_counter = 0
print("\nIt is player no.", player+1, "'s turn!\n")
print("\nPress 'return' to roll the dice.\n"
"To start a new round press 'b'.\n"
"Player", player+1)
roll_dice = input(">>> ")
player += 1 # increment it
if roll_dice == "b":
player = 0 # now your reset should work
throw_per_player_counter = 0
sum_points = 0
print("\n * A new round was started. * \n")

Resources