I want to create a function that counts till 30, but when it reaches 30 I want to reset it to starting point.
def countdown():
global countDown
countDown = int(time.time() - start_time)
return countDown % 30
And then I want to print it like that.
print("You have " + str(30 - countdown()) + " time")
It works but when it reaches 0, it keeps counting below 0 like -1,-2 and it is not doing modula operation. So it doesn't reset itself. What can I do in this case ?
Desired case: 30 29.... 3 2 1 0 30 29 28
Recent case: 30 29 ... 2 1 0 -1 -2
The counter is not being reset using the modulo operator (countDown % 30). Try,
import time
def countdown(i):
counter = i
while True:
if (counter == i):
counter = 0
print(counter)
counter = counter + 1
time.sleep(1)
countdown(30)
What I got from your code
import time
start_time = time.time()
def countdown():
global countDown
countDown = int(time.time() - start_time)
return countDown % 30
print("You have " + str(30 - countdown()) + " time")
is working perfectly on https://www.python.org/shell/
Can't reproduce your problem. Or it's not with the code in your question!
Try to avoid using global variables. Also, use 4 space indentations.
I would use length of time as an input.
from time import time
def do_something():
pass
def get_time(start_time):
# returns how much time did it pass from event that started at start_time
return time() - start_time
def countdown(countDown):
start_time = time()
# this is counter that attains consecutive values [0, 1, ..., countDown]
current_count = 0
while current_count < countDown:
print(countDown - current_count, end=' ')
while get_time(start_time) - current_count < 1:
do_something()
#warning: if do_something takes significant anount of
#time forthcoming print won't be correct
current_count += 1
print(countDown - current_count, end=' ')
return current_count
countdown(7)
countdown(5)
Also the purpose of
print("You have " + str(30 - countdown()) + " time")
is not clear to me. Use it wherever you want in your script.
Due to the question being quite unclear, it is hard to create exactly what you're looking for. However, this code should work for you no matter how you intend it to be used.
This code allows you to:
Make a timer
Get the time left
Run code while the timer is counting down
Run code once the timer has ended.
You can also reset the timer
Code:
import time
class countdown():
def start(self):
self.t = time.time()
def remaining(self):
return 30 - int(time.time()-self.t)
timer = countdown()
timer.start()
while True:
print(30 - countdown(), "seconds remaining") #Still time left code
if timer.remaining() <= 0:
pass #30 seconds over code
timer.reset() #Starts timer again
As others pointed out, your function is not resetting your counter.
Try the following little modification:
def countdown():
global countDown
countDown = int(time.time() - start_time) % 30
return countDown
Firstly, I want to apologize from everyone for not explaining my question clearly because this is my first question. Secondly, as shown in example , I saw that I did not made any mistake about my code. First part is correct but when it prints ("You have " + str(5 - countdown()) + " time") showing me the negative ones because of I take the modula of 30 but showing it in print func " 5 - countdown()" . So when it becomes 15 it will return 15 but 5 - 15 = -10. Thanks for everyone who tried to help.
Related
I'm currently making a stopwatch function, where the user has to input 1 to start and 2 to stop the stopwatch. I'm wondering how to implement the stop function when the while loop is going on as whatever I tried didn't work.
This is the stopwatch code I'm working on:
second = 0
minute = 0
hour = 0
millisecond = 0
start = input("Press 1 to start and 2 to stop: ")
while True:
if start == "2":
break
else:
print("%02d : %02d : %02d "%(hour, minute, second,))
time.sleep(1)
second += 1
if second == 60:
minute += 1
second -= 60
if minute == 60:
hour += 1
minute -= 60
input is blocking until the user types something (and hit enters).
So if you put it in your while loop, the user will get asked repeatedly if he wants to stop, each time pausing the clock, it is not what is expected.
But if you put the input outside the loop (it is strange that you do that), then the user is never asked to type something until the loop ends (which is never).
It means that in your case, input is not a solution.
There is a very similar question which has an accepted answer (slightly adapted to your case) :
try:
while True:
print("%02d : %02d : %02d "%(hour, minute, second,))
...
except KeyboardInterrupt:
# here the loop has definitely stopped
...
which works with Ctrl+C, being a standard way to signal the program to stop something.
If you want to use something other than Ctrl+C, there are other questions here on StackOverflow that could fit your needs :
detecting any keypress in a terminal : How to break this loop in Python by detecting key press
How to kill a while loop with a keystroke?
Your question is thus a duplicate of one of these.
Here's a threading example that does what you describe.
import time
import threading
thread_live = False
def countdown():
seconds = 0;
while thread_live:
hour = seconds // 3600
minute = (seconds // 60) % 60
second = seconds % 60
print("%02d:%02d:%02d "%(hour, minute, second))
seconds += 1
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break
Here's a version that uses a timedelta to store and format the time:
import time
import datetime
import threading
thread_live = False
def countdown():
t = datetime.timedelta(0)
one = datetime.timedelta(seconds=1)
while thread_live:
print(str(t))
t += one
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break
So I wrote this script, which counts income packets on certain port, and in case if there are to many packets script has to do something. On the first received packet is has to start timer, and if timer reaches 60 sec, packet count should start from 0 again. It works, but only for first timer call, in any case, if script has to start timer again I get the error:
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once"`
It's clear, that this thread still running, but i don't understand why. I mean, in case if timer reaches 60 secs, timer loop is finished, and function should be finished too, so i can use timer again? Clearly i don't understand something here, can you guys explain it? Thanks for answers
My code:
from scapy.all import *
from threading import Thread
import time
global count
count = 0
def timer():
global count
i = 0
while i < 60:
if count > 0:
time.sleep(1)
i = i + 1
print(str(count))
else:
print("count is 0, timer turning off...")
break
else:
count = 0
print("60 seconds, timer is off")
background_thread = Thread(target=timer)
def pkt_callback(pkt):
global count
packet_limit = 10
if pkt.haslayer(UDP) and pkt.getlayer(UDP).dport == 5160 and pkt.haslayer(Raw):
raw = pkt.getlayer(Raw).load
s = str(raw)
if 'REGISTER' in s:
count += 1
print(count)
if count == 1:
if background_thread.is_alive() is False:
background_thread.start()
print("Register packet detected, timer is on")
if count >= packet_limit:
print("PACKETLIMIT reached, do smth")
count = 0
sniff(iface='ens160', filter="", prn=pkt_callback)
I think you have to use the return function not break, and either way you have only used it once, also you can change your code a bit, try this:
def timer():
global count
i = 0
while i < 60:
if count != 0:
time.sleep(1)
i += 1
print(str(count))
else:
return "count is 0, timer turning off..."
else:
count = 0
return "60 seconds, timer is off"
I want to run a function every 5 minutes, it must be at a "round" intervals, for example :
12:05:00, 12:10:00, 12:15:00...
It cannot be like this:
12:06:00, 12:11:00, 12:16:00...
Or like this:
12:05:14, 12:10:14, 12:15:14...
What is the most accurate way to do this in python?
You could use a threading.Timer. You have to do some math to calculate the next run time. datetime has a handy replace method for that.
from datetime import datetime, timedelta
from threading import Timer
from time import sleep
import random
def schedule_next_run():
sleep_time = get_sleep_time()
t = Timer(sleep_time, do_work)
t.daemon = True
t.start()
print(f'sleeping for {sleep_time} seconds')
def get_sleep_time():
now = datetime.now()
last_run_time = now.replace(minute=now.minute // 5 * 5, second=0, microsecond=0)
next_run_time = last_run_time + timedelta(minutes=5)
return (next_run_time - now).total_seconds()
def do_work():
now = datetime.now()
print('Doing some work at', now)
sleep(random.uniform(0, 29))
print('Work complete. Scheduling next run.')
schedule_next_run()
print('Starting work schedule')
schedule_next_run()
input('Doing work every 5 minutes. Press enter to exit:\n')
On my system, the function fires within a half millisecond of the target time
Note that the time calculation rounds down and then adds a timedelta to carefully wrap around the end of each hour. You would want to ponder how this will behave around daylight savings changes.
Suggestion: move all this logic to a class to clean it up.
You can use datetime and condition.
import datetime
while True:
current_time = datetime.datetime.now()
if current_time.second % 5 == 0 and current_time.minute % 1 == 0 and current_time.microsecond == 0:
print(current_time)
hope this helps.
import datetime, time
def some_function():
ran_once = True
while True:
current_time = datetime.datetime.now()
if current_time.minute % 5 == 0 and current_time.second % 60 == 0 and not ran_once:
print(current_time) # DO YOUR WORK HERE
ran_once = True
elif current_time.minute % 5 == 0 or current_time.second % 60 != 0:
if current_time.second % 60 == 0:
print("Time to wait:", 5 - (current_time.minute % 5), "minutes and 0 seconds")
else:
print("Time to wait:", 4 - (current_time.minute % 5), "minutes and ", end="")
print(60 - (current_time.second % 60), "seconds")
time.sleep( (4 -(current_time.minute % 5))*60 + 60 -(current_time.second % 60))
ran_once = False
The above code runs at intervals of 5 minutes. Initially, the main thread sleeps for the number of seconds required to reach the perfect timestamp. For example, if the program is started at 7:28:30 then it is going to sleep for 90 seconds and then start at 7:30:00. From then on it will wait for 5 minutes before it runs the required functionality again.
Also, I think the performance of firing up at the exact second really varies on how your system handles the threads.
I am trying to make a text based game in which the user is a pilot in space. I want to create a movement system but am unsure how to do it. I want the user to be able to put in the desired grid coordinates, and his vehicle will begin to change its grid coords to get closer and closer to the ones he inputted.
Now, to do this I will probably need multithreading and a time element. But I am unsure how I can use a time element. Any advice is greatly appreciate, i'm just trying to learn here. Thanks guys!
from Gundam2 import Mobilesuits
#Main Variable/Object declarations:
Leo1=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
Leo2=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
Leo3=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
currentmobilesuit=Leo1
#Main Function declarations
def commands(user_input,currentmobilesuit):
if user_input == "radar":
currentmobilesuit.radar()
elif user_input == "commands":
print("Command list:\nradar")
else:
print("Invalid command\nType 'commands' for a list of valid commands")
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Games typically have a "master loop" of some kind; yours does here:
#Main execution
while True:
commands(raw_input(),currentmobilesuit)
The simplest thing to do is to count in the loop:
#Main execution
turn_count = 0
while True:
commands(raw_input(),currentmobilesuit)
turn_count += 1
If you wanted the real time taken to have some impact on the counter, or be the counter, you can get the current time from the time module calling time.time().
#Main execution
import time
time_start = time.time()
time_elapsed = 0
while True:
commands(raw_input(),currentmobilesuit)
time_elapsed = time.time() - time_start
A couple other thoughts:
Make a Game class, and put the turn counter and game loop in that.
Have the commands function return a number that is the number of time units that took place during the command; for example, entering an invalid command might take 0 turns, while repairing a robot might take 5.
#Main execution
turn_count = 0
while True:
turns_taken = commands(raw_input(),currentmobilesuit)
turn_count += turns_taken
You can use non-blocking I/O. This will help you avoid the complications of threading. Here's your sample code implemented with a non-blocking read of stdin:
#!/usr/bin/python
import sys
import select
call_count = 0
#Main Function declarations
def commands(user_input):
global call_count
if len(user_input) > 0:
print('call count: ' + str(call_count) + ' user entered: ' + user_input)
def raw_input_no_block():
global call_count
call_count = call_count + 1
input_avail = select.select([sys.stdin], [], [], 0.1)[0] #wait for 0.1 seconds
if input_avail:
return sys.stdin.readline()
else:
return ''
#Main execution
while True:
commands(raw_input_no_block())
I have a homework assignment to do and I really need a solution. I have been trying to do this since yesterday but I do not know how.
Program has to generate and print a letter or a number and then a user has to type it as quickly as possible and press ENTER. The game is over after 30 secs.
Well I do not know how to put time limit to a game. I was searching through stackoverflow and I did not find anything useful. Please help me.
**Here it is what I have done so far. I tried code from the answer by SYSS.STDER, but it does not quite work because when the 30 secs are over, the game should also be over, but here in this code the game is over when I type last character.
LOOP WILL NOT STOP UNTIL IT FINISHES AND WE DISCOVER THAT WE ARE PAST OUR DEADLINE. THE TASK NEEDS TO BE INTERRUPTED IN PROGRESS AS SOON AS THE TIME ELAPSES.
max_time =30
start_time = time.time() # remember when we started
while (time.time() - start_time) < max_time:
response = "a" # the variable that will hold the user's response
c = "b" #the variable that will hold the character the user should type
score = 0
number = 0
c = random.choice(string.ascii_lowercase + string.digits)
print(c)
number = number + 1
response = input("Type a letter or a number: ") #get the user's response
if response == c and (time.time() - start_time) < max_time:
# if the response from the previous loop matches the character
# from the previous loop, increase the score.
score = score + 1
Here's my way to do it:
import string
import random
import time
response = "a" # the variable that will hold the user's response
c = "b" #the variable that will hold the character the user should type
score = 0 #the variable that will hold the user's score
start = time.time() #the variable that holds the starting time
elapsed = 0 #the variable that holds the number of seconds elapsed.
while elapsed < 30: #while less than 30 seconds have elapsed
if response == c: #if the response from the previous loop matches the character
score += 1 #from the previous loop, increase the score.
#c is a random character
c = random.choice(string.ascii_lowercase + string.digits)
print(c)
response = input("Type a letter or a number: ") #get the user's response
elapsed = time.time() - start #update the time elapsed
Since you're using Windows you can use the msvcrt.kbhit function to check for keypresses inside timing loops:
import msvcrt #### windows only ####
import os
import random
import string
import time
max_time = 15
def readch(echo=True):
"Get a single character on Windows"
ch = msvcrt.getch()
while ch in b'\x00\xe0': # special function key?
msvcrt.getch() # get keycode & ignore
ch = msvcrt.getch()
if echo:
msvcrt.putch(ch)
return ch.decode()
def elapsed_time():
global start_time
return time.time() - start_time
number = 0
score = 0
start_time = time.time() # initialize timer
while elapsed_time() < max_time:
c = random.choice(string.ascii_lowercase + string.digits)
print(c, end='')
number += 1
print("Type a letter or a number: ", end='')
while elapsed_time() < max_time:
if not msvcrt.kbhit():
time.sleep(0.1) # don't hog processor
else:
response = readch(echo=False) # get the user's response
if response == c:
print(response) # only print if correct
score += 1
break
else:
print()
print()
print("Time's up")
print("You go {} out of {}:".format(score, number))
A sample program to exit prime number function when Time limit has exceeded.
import math
from time import time
start_time = time()
max_time = 2
def prime(n):
for i in range(2, int(math.sqrt(n))):
if(time() - start_time) > max_time:
return "TLE"
if n % i == 0:
return False
return True
print(prime(3900000076541747077))
use "timeit" module available in python for better result.