Continous loop and exiting in python
I have a script that runs continuously when invoked and every 5 minutes checks my gmail inbox. To get it to run every 5 minutes I am using the time.sleep() function. However I would like user to end the script anytime my pressing q, which it seems cant be done when using time.sleep(). Any suggestions on how i can do this?
You can use select() on sys.stdin combined with a timeout. Roughly speaking, your main loop will look like this (untested):
while True: r,w,e = select.select([sys.stdin], , , 600) if sys.stdin in r: # data available on sys.stdin if sys.stdin.read() == 'q': break # do gmail stuff
To be able to read a single character from stdin you will need to put stdin in unbuffered mode. An alternative is described here. If you want to keep things simple, just require the user to hit enter after the 'q'
The -u flag I mentioned earlier won't work: it may put pyton in unbuffered mode but not your terminal.
Alternatively, ncursus may be of help here. I'm merely hinting, I don't have much experience with this; if I want a fancy user interface, I'd use TkInter.
Ok. try this python code... (Tested in linux. Most probably wont work on Windows - thanks to Aaron's input on that)
This is derived (copied and modified) from http://code.activestate.com/recipes/572182-how-to-implement-kbhit-on-linux/
import sys, termios, atexit from select import select delay = 1 # in seconds - change this for your needs # save the terminal settings fd = sys.stdin.fileno() new_term = termios.tcgetattr(fd) old_term = termios.tcgetattr(fd) # new terminal setting unbuffered new_term = (new_term & ~termios.ICANON & ~termios.ECHO) # switch to normal terminal def set_normal_term(): termios.tcsetattr(fd, termios.TCSAFLUSH, old_term) # switch to unbuffered terminal def set_curses_term(): termios.tcsetattr(fd, termios.TCSAFLUSH, new_term) def getch(): return sys.stdin.read(1) def kbhit(): dr,dw,de = select([sys.stdin], , , delay) return dr <>  def check_mail(): print 'Checking mail' if __name__ == '__main__': atexit.register(set_normal_term) set_curses_term() while 1: if kbhit(): ch = getch() break check_mail() print 'done'
If you really wanted to (and wanted to waste a lot of resources), you could cut your loop into 200 ms chunks. So sleep 200 ms, check input, repeat until five minutes elapse, and then check your inbox. I wouldn't recommend it, though.
While it's sleeping, though, the process is blocked and won't receive input until the sleep ends.
Oh, as an added note, if you hit the key while it's sleeping, it should still go into the buffer, so it'll get pulled out when the sleep ends and input is finally read, IIRC.