[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Exception on keypress

Michael Goerz

2/14/2008 1:27:00 PM

Hi,

I'm writing a command line program that watches a file, and recompiles
it when it changes. However, there should also be a possibility of doing
a complete clean restart (cleaning up temp files, compiling some
dependencies, etc.).

Since the program is in an infinite loop, there are limited means of
interacting with it. Right now, I'm using the Keyboard Interrupt: if the
user presses CTRL+C once, a clean restart is done, if he presses it
twice within a second, the program terminates. The stripped down code
looks like this:

while True:
try:
time.sleep(1)
if watched_file_has_changed():
compile_the_changed_file()
except KeyboardInterrupt: # user hits CTRL+C
try:
print("Hit Ctrl+C again to quit")
time.sleep(1)
clean_restart()
except KeyboardInterrupt:
do_some_cleanup()
sys.exit(0)

Is there another way of doing this? Ideally, there would be an exception
every time any key at all is pressed while the code in the try block is
being executed. That way, the user could just hit the 'R' key to do a
clean restart, and the 'E' key to exit the program. Is there any way to
implement something like that?

Right now, the CTRL+C solution works, but isn't very extensible (It
wouldn't be easy to add another command, for example). Any suggestions?

Thanks,
Michael
4 Answers

Francesco Bochicchio

2/14/2008 4:33:00 PM

0

On 14 Feb, 14:27, Michael Goerz <newsgroup898s...@8439.e4ward.com>
wrote:
> Hi,
>
> I'm writing a command line program that watches a file, and recompiles
> it when it changes. However, there should also be a possibility of doing
> a complete clean restart (cleaning up temp files, compiling some
> dependencies, etc.).
>
> Since the program is in an infinite loop, there are limited means of
> interacting with it. Right now, I'm using the Keyboard Interrupt: if the
> user presses CTRL+C once, a clean restart is done, if he presses it
> twice within a second, the program terminates. The stripped down code
> looks like this:
>
>      while True:
>          try:
>              time.sleep(1)
>              if watched_file_has_changed():
>                  compile_the_changed_file()
>          except KeyboardInterrupt: # user hits CTRL+C
>              try:
>                  print("Hit Ctrl+C again to quit")
>                  time.sleep(1)
>                  clean_restart()
>              except KeyboardInterrupt:
>                  do_some_cleanup()
>                  sys.exit(0)
>
> Is there another way of doing this? Ideally, there would be an exception
> every time any key at all is pressed while the code in the try block is
> being executed. That way, the user could just hit the 'R' key  to do a
> clean restart, and the 'E' key to exit the program. Is there any way to
> implement something like that?
>
> Right now, the CTRL+C solution works, but isn't very extensible (It
> wouldn't be easy to add another command, for example). Any suggestions?
>
> Thanks,
> Michael

I don't know any way to extend your solution. However, I would suggest
to experiment with the threading
module. Threading in Python is quite easy, as long as that you stick
with queue and events for communications
between threads.

Here is an example, where the main thread is used to handle the
console and the background thread does the job.
The assumption is that the background thread can do the job in
separate short steps, checking for new commands between steps.
This esemple uses events to signal commands to the background thread
and uses a queue to send from background thread
to main thread synchronous messages to be displayed on the console. I
guess the example could be shorter if I used a command queue instead
of events, but I wanted to show how to use events.

The program works, but surely can be improved ...

Ciao
--------
FB

#
# Example of program with two threads
# one of MMI, one background
#

import sys, traceback

import threading, time, Queue

class BackgroundThread(threading.Thread):
TICK = 1.0
def __init__(self, msg_queue):
threading.Thread.__init__(self)
self.reset_event = threading.Event()
self.quit_event = threading.Event()
self.msg_queue = msg_queue

def do_job(self):
pass # This shoud execute each time a step and return shortly

def do_reset(self):
pass

def run(self):
while not self.quit_event.isSet():
self.do_job() # should be one short step only
time.sleep(self.TICK)
if self.reset_event.isSet():
self.do_reset()
self.reset_event.clear()
self.msg_queue.put('Reset completed')


def main():
msg_queue = Queue.Queue()
print 'Starting background thread ...'
b_thread = BackgroundThread(msg_queue)
b_thread.start()
while 1:
print 'Type R to reset'
print 'Type Q to quit'
cmd = raw_input('Command=>')
if cmd in 'Rr':
b_thread.reset_event.set()
# wait for reset command completion
print msg_queue.get()
elif cmd in 'qQ':
b_thread.quit_event.set()
break

print 'Waiting the background thread to terminate ...'
b_thread.join()
print 'All done.'

if __name__ == '__main__':
try:
main()
print 'Program completed normally.'
raw_input('Type something to quit')
except:
err, detail, tb = sys.exc_info()
print err, detail
traceback.print_tb(tb)
raw_input('Oops...')






Dennis Lee Bieber

2/14/2008 6:00:00 PM

0

On Thu, 14 Feb 2008 14:27:22 +0100, Michael Goerz
<newsgroup898sfie@8439.e4ward.com> declaimed the following in
comp.lang.python:

> Is there another way of doing this? Ideally, there would be an exception
> every time any key at all is pressed while the code in the try block is
> being executed. That way, the user could just hit the 'R' key to do a
> clean restart, and the 'E' key to exit the program. Is there any way to
> implement something like that?
>
If running under some variant of M$ Windows, the msvcrt module might
be useful... In particular:

msvcrt.kbhit()
msvcrt.getch()

The first is a keyboard poll, the second actually reads a character
without echoing it. Granted, I normally abhor polling loops, but since
your process is already a timed-poll...

while True:
time.sleep(0.1) #or whatever to avoid too much CPU hogging
if msvcrt.kbhit():
cmd = msvcrt.getch().lower()
if cmd == "e": break
if cmd == "r":
#do whatever cleanup is needed, etc.
else:
#check for file changes and do the current work

UNIX/Linux systems need to do nasty things with low-level I/O
settings...
--
Wulfraed Dennis Lee Bieber KD6MOG
wlfraed@ix.netcom.com wulfraed@bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: web-asst@bestiaria.com)
HTTP://www.bestiaria.com/

plainolamerican

3/31/2014 9:48:00 PM

0

On Monday, March 31, 2014 12:17:49 PM UTC-5, The Peeler wrote:
> On Mon, 31 Mar 2014 09:30:23 -0700 (PDT), plainstupidamerican wrote:
>
>
>
>
>
> >>
>
> >> found," Elkin said. "Israel is among the friendliest countries to the US and
>
> >>
>
> >> there is no reason why we shouldn't be part of the program."
>
> >>
>
> >> ____
>
> >
>
> > 80% increase in US rejections of Israeli visa requests
>
> > ---
>
> > because jews kill our soldiers, extort our politicians and promote socialism.
>
>
>
> LOL Oh, look, a stupid American with a HUGE inferiority complex! Of course,
>
> like any rabid antisemite, he is just another psychiatric case! LOL

just stating the facts about traitorous jews.
they outnumber muzzies in our prisons and can't be trusted as citizens.

The Peeler

3/31/2014 10:06:00 PM

0

On Mon, 31 Mar 2014 14:47:56 -0700 (PDT), plainstupidamerican wrote:


>>> because jews kill our soldiers, extort our politicians and promote socialism.
>>
>> LOL Oh, look, a stupid American with a HUGE inferiority complex! Of course,
>>
>> like any rabid antisemite, he is just another psychiatric case! LOL
>
> just stating the facts about traitorous jews.
> they outnumber muzzies in our prisons and can't be trusted as citizens.

LOL!!!!!!!! Oh, yeah, you ARE another SEVERE psychiatric case!