run a basic digital clock in the python shell

DanMcGrew picture DanMcGrew · May 30, 2016 · Viewed 26.6k times · Source

I want to code simple digital clock in the python shell. I want to avoid using tkinter if possible. This is what I currently have;

import time
while True:
    from datetime import datetime
    now = datetime.now()  
    print ("%s/%s/%s %s:%s:%s" % (now.month,now.day,now.year,now.hour,now.minute,now.second)) 
    time.sleep(1)

This produces a recurring print out, something like this;

06/29/16 23:08:32

06/29/16 23:08:33

06/29/16 23:08:34

I know this is crude, I'm still learning. I just want one line with a "ticking" digital clock in the shell. I'm using python 3.5.1 on idle and windows 10.

If this isn't possible, I'd very much like to know why.

Kindest thanks

Answer

slugonamission picture slugonamission · May 30, 2016

If you're just printing out a fixed length output like this each time, you can use the carriage return character to rewind to the start of the line, as long as you don't print a newline. Example:

# Note trailing comma, that suppresses the newline in Python
print ("%s/%s/%s %s:%s:%s" % (now.month,now.day,now.year,now.hour,now.minute,now.second)),

# Now rewind back to the start of the line. Again, not trailing comma
print("\r"),

Now, you may also notice that nothing is ever printed to the screen. This is because standard out is buffered, so you can flush with this:

# At the top...
import sys

# In the loop, after the first print
sys.stdout.flush()

This all works as follows. Imagine that there is actually a cursor on screen. You first print out the time with the first print (and the flush), then you move the cursor back to the start of the line with print("\r"),. This doesn't actually remove any of the characters, it just moves the cursor. You then write the next time out again. Because it nicely happens to be the exact same length, the time gets written out again, replacing the old characters.

The resulting script is then as follows:

import time
import sys

while True:
    from datetime import datetime
    now = datetime.now()
    print ("%s/%s/%s %s:%s:%s" % (now.month,now.day,now.year,now.hour,now.minute,now.second)),
    sys.stdout.flush()
    print("\r"),
    time.sleep(1)

If you want finer grained control over what's going on, you can start using the curses library, but I imagine that's overkill for what you're trying to do here.

EDIT: As @PadraicCunningham mentioned in the comments, the correct syntax to suppress newline printing in Python 3 and force the contents to flush to the screen is the following:

print("hello", flush=True, end="")

Also, as @AlexHall mentions, the print statement does not actually print a fixed width statement; so to do this, we should use strftime() instead.

Therefore the correct program is:

import time

while True:
    from datetime import strftime
    print (strftime("%m/%d/%Y %H:%M:%S"), end="", flush=True)
    print("\r", end="", flush=True)
    time.sleep(1)