简体   繁体   中英

How to make a timer program in Python

Here is my goal: To make a small program (text based) that will start with a greeting, print out a timer for how long it has been since the last event, and then a timer for the event. I have used this code to start out with trying to figure out a timer, but my first problem is that the timer keeps repeating on a new line with each new second. How do I get that to stop? Also, this timer seems to lag behind actual seconds on the clock.

import os
import time


s=0
m=0

while s<=60:
    os.system('cls')
    print (m, 'Minutes', s, 'Seconds')
    time.sleep(1)
    s+=1
    if s==60:
        m+=1
        s=0

I would go with something like this:

import time
import sys

time_start = time.time()
seconds = 0
minutes = 0

while True:
    try:
        sys.stdout.write("\r{minutes} Minutes {seconds} Seconds".format(minutes=minutes, seconds=seconds))
        sys.stdout.flush()
        time.sleep(1)
        seconds = int(time.time() - time_start) - minutes * 60
        if seconds >= 60:
            minutes += 1
            seconds = 0
    except KeyboardInterrupt, e:
        break

Here I am relying on actual time module rather than just sleep incrementer since sleep won't be exactly 1 second.

Also, you can probably use print instead of sys.stdout.write , but you will almost certainly need sys.stdout.flush still.

Like:

print ("\r{minutes} Minutes {seconds} Seconds".format(minutes=minutes, seconds=seconds)),

Note the trailing comma so a new line is not printed.

This is my version. It's great for beginners.

     # Timer
import time
print("This is the timer")
# Ask to Begin
start = input("Would you like to begin Timing? (y/n): ")
if start == "y":
    timeLoop = True

# Variables to keep track and display
Sec = 0
Min = 0
# Begin Process
timeLoop = start
while timeLoop:
    Sec += 1
    print(str(Min) + " Mins " + str(Sec) + " Sec ")
    time.sleep(1)
    if Sec == 60:
        Sec = 0
        Min += 1
        print(str(Min) + " Minute")
# Program will cancel when user presses X button

On my PC (Windows 7) when run in a cmd window, this program works almost exactly as you say it should. If the timer is repeating on a new line with each second, that suggests to me that os.system ('cls') is not working for you -- perhaps because you're running on an OS other than Windows?

The statement while s<=60: appears to be incorrect because s will never be equal to 60 in that test -- anytime it gets to 60, it is reset to 0 and m is incremented. Perhaps the test should be while m<60: ?

Finally, on my PC, the timer does not appear to lag behind actual seconds on the clock by much. Inevitably, this code will lag seconds on the clock by a little -- ie however long it takes to run all the lines of code in the while loop apart from time.sleep(1) , plus any delay in returning the process from the sleeping state. In my case, that isn't very long at all but, if running that code took (for some reason) 0.1 seconds (for instance), the timer would end up running 10% slow compared to wall clock time. @sberry's answer provides one way to deal with this problem.

Ok, I'll start with why your timer is lagging.

What happens in your program is that the time.sleep() call "sleeps" the program's operation for 1 second, once that second has elapsed your program begins execution again. But your program still needs time to execute all the other commands you've told it to do, so it takes 1s + Xs to actually perform all the operations. Although this is a very basic explanation, it's fundamentally why your timer isn't synchronous.

As for why you're constantly printing on a new line, the print() function has a pre-defined end of line character that it appends to any string it is given.

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

You can overwrite this with anything by putting end="YourThing" in your print statement like so

for x in range(3):
    print("Test", end="")

The above example appends an empty string to the end of the line, so the output of the loop would be

"TestTestTest"

As for solving your timer problem, you should use something similar to

timePoint = time.time()

while True:

    #Convert time in seconds to a gmtime struct
    currentTime = time.gmtime(time.time() - timePoint))

    #Convert the gmtime struct to a string
    timeStr = time.strftime("%M minutes, %S seconds", currentTime)

    #Print the time string
    print(timeStr, end="")

Use the timeit module to time your code. Then adjust the time.sleep(x) accordingly. For example, you could use one of the following:

import timeit
#Do all your code and time stuff and while loop
#Store that time in a variable named timedLoop
timer = 1- timedLoop

#Inside while loop:
   time.sleep(timer)

This will time the code you have other than the time.sleep, and subtract that from 1 second and will sleep for that amount of time. This will give an accurate representation of 1 second. Another way is less work, but may not be as accurate:

#set up timeit module in another program and time your code, then do this:
#In new program:
timer = 1 - timerLoop
print timerLoop

Run your program, then copy the printed time and paste it into program two, the one you have now. Use timerLoop in your time.sleep():

time.sleep(timerLoop)

That should fix your problem.

# Timer
import time
import winsound
print "               TIMER"
#Ask for Duration
Dur1 = input("How many hours?  : ")
Dur2 = input("How many minutes?: ")
Dur3 = input("How many seconds?: ")
TDur = Dur1 * 60 * 60 + Dur2 * 60 + Dur3
# Ask to Begin
start = raw_input("Would you like to begin Timing? (y/n): ")
if start == "y":
    timeLoop = True

# Variables to keep track and display
CSec = 0
Sec = 0
Min = 0
Hour = 0
# Begin Process
timeLoop = start
while timeLoop:
    CSec += 1
    Sec += 1
    print(str(Hour) + " Hours " + str(Min) + " Mins " + str(Sec) + " Sec ")
    time.sleep(1)
    if Sec == 60:
        Sec = 0
        Min += 1
        Hour = 0
        print(str(Min) + " Minute(s)")
    if Min == 60:
        Sec = 0
        Min = 0
        Hour += 1
        print(str(Hour) + " Hour(s)")
    elif CSec == TDur:
        timeLoop = False
        print("time\'s up")
        input("")
    while 1 == 1:
        frequency = 1900  # Set Frequency To 2500 Hertz
        duration = 1000  # Set Duration To 1000 ms == 1 second
        winsound.Beep(frequency, duration)

I based my timer on user5556486's version. You can set the duration, and it will beep after said duration ended, similar to Force Fighter's version

# This Is the Perfect Timer!(PS: This One Really Works!)
import sys
import time
import os

counter=0
s = 0
m = 0
n = int(input("Till How Many Seconds do you want the timer to be?: "))
print("")

while counter <= n:
    sys.stdout.write("\x1b[1A\x1b[2k")
    print(m, 'Minutes', s, 'Seconds')
    time.sleep(1)
    s += 1
    counter+=1
    if s == 60:
        m += 1
        s = 0

print("\nTime Is Over Sir! Timer Complete!\n")

The ideas are pretty cool on other posts -- however, the code was not useable for what I wanted to do.

I liked how people want to subtract time, in this way you don't have to have a time.sleep()

from datetime import datetime

timePoint = time.time()
count = 0
while (count < 10):
    timePoint2 = time.time()
    timePointSubtract = timePoint2 - timePoint
    timeStamp1 = datetime.utcfromtimestamp(timePointSubtract).strftime('%H:%M:%S')
    print(f'{count} and {timeStamp1}')
    val = input("")
    count = count + 1

So, pretty much I wanted to have a timer but at the same time keep track of how many times I pressed enter.

Here my answer.

import time
import sys

time_start = time.time()

hours = 0
seconds = 0
minutes = 0

while True:

    sys.stdout.write("\r{hours} Hours {minutes} Minutes {seconds} Seconds".format(hours=hours, minutes=minutes, seconds=seconds))
    sys.stdout.flush()
        
    if (seconds <= 59):
        time.sleep(1)
        seconds += 1

        if (minutes <= 59 and seconds == 59 + 1):
            minutes += 1

            if (minutes == 60 and seconds == 59 + 1 ):
                hours += 1
                minutes = 0
                seconds = 0

    else:
        seconds = 0

This seems like it would be MUCH easier:

#!/usr/bin/env python
from datetime import datetime as dt
starttime = dt.now()
input("Mark end time")
endtime = dt.now()
print("Total time passed is {}.".format(endtime-starttime))

a simple timer program that has sound to remind you would be:

from time import sleep
import winsound
m = 0
print("""**************************
Welcome To FASTIMER®
**************************""")
while True:
    try:
        countdown = int(input("How many seconds:  "))
        break
    except ValueError:
        print("ERROR, TRY AGAIN")
original = countdown
while countdown >= 60:
    countdown -= 60
    m += 1
for i in range (original,0,-1):
    if m < 0:
        break
    for i in range(countdown,-2,-1):
        if i % 60 == 0:
            m-=1
        if i == 0:
            break
        print(m," minutes and ",i," seconds")
        sleep(1)
    if m < 0:
        break
    for j in range(59,-1,-1):
        if j % 60 == 0:
            m-=1          
        print(m," minutes and ",j," seconds")
        sleep(1)
print("TIMER FINISHED")
winsound.PlaySound('sound.wav', winsound.SND_FILENAME)

this program uses time.sleep() to wait a second. It converts every 60 seconds to a minute. the sound only works with Windows or you can install pygame to add sounds.

I have a better way:

import time
s=0
m=0
while True:
  print(m,  'minutes,', s, 'seconds')
  time.sleep(0.999999999999999999999) # the more 9s the better
  s += 1
  if s == 60:
    s=0
    m += 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM