Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Program that either waits for user input or runs at defined intervals?

I currently have a program that runs at regular intervals. Right now the program runs continuously, checking for new files every 30 minutes:

def filechecker():
    #check for new files in a directory and do stuff

while True:
    filechecker()
    print '{} : Sleeping...press Ctrl+C to stop.'.format(time.ctime())
    time.sleep(1800)

However, I'd also like the user to be able to come to the terminal and enter a keystroke to manually call filechecker() instead of either waiting for the program from waking from sleep or having to relaunch the program. Is this possible to do? I tried to look at using threading, but I couldn't really figure out how to wake the computer from sleep (don't have much experience with threading).

I know I could just as easily do :

while True:
    filechecker()
    raw_input('Press any key to continue')

for full manual control, but I want my to have my cake and eat it too.

like image 842
qRTPCR Avatar asked Mar 17 '23 07:03

qRTPCR


2 Answers

You can use a try/except block with KeyboardInterrupt (which is what you get with Ctrl-C while in the time.sleep(). Then in the except, ask the user if they want to quit or run filechecker immediately. Like:

while True:
    filechecker()
    try:
        print '{0} : Sleeping...press Ctrl+C to stop.'.format(time.ctime())
        time.sleep(10)
    except KeyboardInterrupt:
        input = raw_input('Got keyboard interrupt, to exit press Q, to run, press anything else\n')
        if input.lower() == 'q':
            break
like image 178
clindseysmith Avatar answered Mar 18 '23 21:03

clindseysmith


The solution provided by clindseysmith introduces one more key press than what the original question was asking for (at least, my interpretation thereof). If you really want to combine the effect of the two snippets of code in the question, i.e., you don't want to have to press Ctrl+C for calling the file checker immediately, here's what you can do:

import time, threading

def filechecker():
    #check for new files in a directory and do stuff
    print "{} : called!".format(time.ctime())

INTERVAL = 5 or 1800
t = None

def schedule():
    filechecker()
    global t
    t = threading.Timer(INTERVAL, schedule)
    t.start()

try:
    while True:
        schedule()
        print '{} : Sleeping... Press Ctrl+C or Enter!'.format(time.ctime())
        i = raw_input()
        t.cancel()
except KeyboardInterrupt:
    print '{} : Stopped.'.format(time.ctime())
    if t: t.cancel()

The variable t holds the id of the thread that is scheduled next to call the file checker. Pressing Enter cancels t and reschedules. Pressing Ctrl-C cancels t and stops.

like image 28
nickie Avatar answered Mar 18 '23 21:03

nickie