1

I have a test case I'm building up whereby I want to start or stop a timer with a keypress, but I can't figure out how to keep my routine alive... 'g' should start the timer (and continually repeat), and 's' should stop the timer. 'g' can then start the timer, etc. Instead, 'g' starts the timer and 's' does nothing. What am I doing wrong?

Code:

#!/usr/bin/env python

import time, sys 

def print_something(status):
    while(status):
        print 'the time: ' , time.ctime()
        time.sleep(1);

def main():
    result = 1 
    print 'starting time: ' , time.ctime()

    result = raw_input('press g to start timer, s to stop.\n')
    while(result is 'g'):
        print_something(True)
        result = ''

    result = None
    time.stop()

main()
jml
  • 1,745
  • 6
  • 29
  • 55

2 Answers2

1

Your main problem is that you are trying to read from stdin but the control flow is stuck in the print_something function (which in this case is an infinite loop) and simply won't leave from there. In other words, you want to read the 's' as the user inputs it but that part of the code will not be executed until the loop is finished.

You'll need some sort of interruption. The following code accomplishes what you want, however, the user has to press "Ctrl+C" to stop the timer.

#!/usr/bin/env python

import time, sys 

def main():
    result = 1 
    print 'starting time: ' , time.ctime()

    while(result):
        result = raw_input('press g to start timer, ctrl+c to stop.\n')

        if result is 'g':
            print_something()
            result = ''
        else:
            result = None
            time.stop()
            sys.exit()

def print_something():
    while 1:
        try:
            print 'the time: ' , time.ctime()
            time.sleep(1);
        except KeyboardInterrupt:            
            break
main()

EDIT:

Here's what I want: 1. start program 2. hit g, timer starts 3. hit s, timer stops 4. hit g, timer starts, etc. CTRL-C should not be the way to stop the timer, but rather to kill the program.

Then the programming paradigm has to change. You are thinking of an Event-driven program which responds to events such as key presses. Perhaps you'll need to create a thread which retrieves which key is pressed and acts accordingly if s or g were pressed while another thread prints the time.

PALEN
  • 2,784
  • 2
  • 23
  • 24
  • OK, let's say that I don't want to call sys.exit(), but simply stop the timer. I attempt that and again am not able to interrupt. This is the heart of the problem I'm attempting to solve. – jml Feb 26 '13 at 04:03
  • @jml Suppresing the `sys.exit()` line from the code above will simply stop the timer and you can add more code to be executed from there – PALEN Feb 26 '13 at 04:06
  • @jml then change `else:` to `elif result is 's':` and it will only do the `sys.exit()` after it gets `s` from the command line (after the ctrl-c of course) – askewchan Feb 26 '13 at 04:06
  • @PALEN: Here's what I want: 1. start program 2. hit g, timer starts 3. hit s, timer stops 4. hit g, timer starts, etc. CTRL-C should not be the way to stop the timer, but rather to kill the program. I've now updated my question to exemplify more clearly the issue. – jml Feb 26 '13 at 04:18
  • There's got to be a way to do this via a subprocess or similar. Your suggestion regarding creating a thread would be a fine answer, but I have no idea how to do that. I'll look into it. – jml Feb 26 '13 at 04:37
  • @jml Indeed, I can write the code which handles threads as I mentioned in the edit above and that's not a problem. What I'm not familiar with is how to determine which key was pressed in python. That topic is discussed here: http://stackoverflow.com/questions/694296/detect-in-python-which-keys-are-pressed. It depends of the platform you want to work with, perhaps you could use PyKeylogger. – PALEN Feb 26 '13 at 04:42
  • Can't you just use raw_input()? I'm on osx; I'll update tags. – jml Feb 26 '13 at 04:45
  • 1
    Working via command line you can't because the screen will not be updated (that is nothing will be printed) until the user inputs something. In other words, the program will keep waiting for user input and won't (constantly) print the time – PALEN Feb 26 '13 at 04:56
  • I'm marking this correct because I feel it's as "right as it can get". My original question involved the command line key input, and I don't think there's an easy way to implement it with the original parameters I'd given. Since the scope of the problem has changed, I'll post another question on threading/subprocess management at a later time when I have implemented some tests. – jml Feb 26 '13 at 05:05
  • @jml By the way, if the s key is not that important to what you wanna do, you could make an infinite loop that starts the timer every time g is input and stops it every time Ctrl+C is pressed. – PALEN Feb 26 '13 at 05:12
-1

Try moving your while loop inside of the main function.

def main():
result = 1
print 'starting time: ' , time.ctime()
while(result):
result = raw_input('press g to start timer, s to stop.\n')

if result is 'g':
    print_something()
    result = ''
elif result is 's':
    result = None
    time.stop()
    sys.exit()

Update: Have you tried testing for while(result != 's') ?

chirinosky
  • 4,438
  • 1
  • 28
  • 39