0

Below is the code of a simple timer that prints out a new number in the command line every 0.1 sec, and -- simultaneously -- awaits for a keypress (Enter). As soon as Enter is pressed, the timer is switched into pause, stops printing and waits for another Enter keypress that would resume counting / printing.

The problem I face is that while in the 'pause' state, CPU consumption grows to almost 100% (and seems to be below 1% while running / printing out).

Why is it? What am I doing wrong?

Here goes the code:

import time, thread, sys

time_passed = 0
l = []
trig = True

def input(l):
    """ Waits for a keypress """
    raw_input()
    l.append(None)

def timer():
    """ Prints out a number every millisecond """
    global time_passed
    time.sleep(.1)
    time_passed += 1
    sys.stdout.write(format(time_passed)+"\r")
    sys.stdout.flush()

def running():
    """ Toggles play/pause state if Enter is pressed """
    global trig, l
    while trig:
        timer()
        if l:
            l = []
            trig = False
            return trig, l

def stopped():
    """ Toggles pause/play state if Enter is pressed """
    global trig, l
    while not trig:
        if l:
            l = []
            trig = True
            return trig, l

def main():
    """ Waits for a keypress while either running or stopping the timer """
    global l, trig
    while True:
        thread.start_new_thread(input, (l,))
        if trig:    # The timer is running
            running()
        else:       # The timer is stopped
            stopped()

main()

Thank you.

1 Answer 1

1

Well, if its in a "stopped" state you run this:

def stopped():
    """ Toggles pause/play state if Enter is pressed """
    global trig, l
    while not trig:
        if l:
            l = []
            trig = True
            return trig, l

this loop has no pause/wait. So it runs at full speed without getting back to system, while within the running you do call time.sleep. Putting time.sleep(0.1) before the if will make it work as you wish.

Also a friendly personal note, you could refactor it a little bit. Two functions with the same description working on globals make it a little bit hard to understand =).

I'd make something like:

import time, thread, sys, threading

time_passed = 0
l = []

def input(l):
    """ Waits for a keypress """
    raw_input()
    l.append(None)

def timer():
    """ Prints out a number every millisecond """
    global time_passed
    time_passed += 1
    sys.stdout.write(format(time_passed)+"\r")
    sys.stdout.flush()

def running(state):
    """ Toggles play/pause state if Enter is pressed """
    global l
    while True:
        time.sleep(.1)
        if state:
            timer()
        if l:
            l = []
            state = not state
            return state

def main():
    """ Waits for a keypress while either running or stopping the timer """
    global l
    state = True
    while True:
        thread.start_new_thread(input, (l,))
        state = running(state)

main()

and I would think how to signal the toggle better. I somehow don't like the idea of returning from the function, you don't need really to return from running, just flip the state. But it is just personal preference I guess.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! As for refactoring, those functions, running() and stopped() do not have exactly the same description :) (but I do agree, it may be quite misleading). I used to have 'em integrated in main(), do you think it'd be better?
I edited the answer and added refactored version of running, that bases its behaviour on a state passed as an argument. I still think that two while True loops are too much, but I think the code is easier to understand this way. You can pass it through Code Review SE. They are better at this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.