Sunday, November 15, 2009

Getting Out of The Python's Loops

Python is a great language - I used it many times for measurement automation. The only thing I stumbled on from time to time was a simple control over long time or infinite loops. When the loop is running it should check for a key or a button been pressed without stopping and waiting for input. Such stopping and waiting happens, for example, when a function like getch() is used.

The case in general looks like this:
while 1:
print 1,
and the problem is how to get out of the loop gracefully without killing the program.

I'm aware of the following variants to deal with the situation:
  1. Ctrl-C/Crtl-D keyboard program termination. It works but kills whole program. It is possible to avoid that by exception processing of the error:
    try:
    while 1:
    print 1,
    # on ctrl-d or ctrl-c
    except (EOFError, KeyboardInterrupt):
    print '\n exception handled'
    print 'Clean Exit on Ctrl-C/D'

  2. Tkinter - it allows to stop looping on event as "button pressed":
    import time
    from Tkinter import *

    class App:

    Var = 1

    def __init__(self, master):
    frame = Frame(master)
    frame.pack()

    self.button = Button(frame, text="QUIT",
    command=frame.quit)
    self.button.pack(side=LEFT)

    self.stoploop = Button(frame, text="Stop",
    command=self.stopLoop)
    self.stoploop.pack(side=LEFT)

    while self.Var == 1:
    time.sleep(1)
    print self.Var,

    print "\nClean exit from the loop"

    def stopLoop(self):
    self.Var = 0
    print "Var = %d" % self.Var

    root = Tk()
    app = App(root)
    root.mainloop()

  3. Loop in a separate thread (similar to Tkinter variant) - I came up with this idea before finding other better solutions: if the loop is running in a separate thread then user still has access to the main program from keyboard and hence can control the loop too:
    import threading, time

    class LoopThread (threading.Thread):

    Value = 0
    Counts = 0

    def run(self):
    print 'Loop is started'
    while self.Value != 10:
    time.sleep(1)
    self.Counts = self.Counts + 1
    print 'Loop was ended, Counts %d' % self.Counts

    def getVal(self):
    return self.Value

    def setVal(self, Val):
    self.Value = Val

    # Create the object
    MyLoop = LoopThread()

    # Start the thread
    MyLoop.start()

    # Send the loop termination value from
    # the main program whenever you need
    time.sleep(11)
    MyLoop.setVal(10)
    A disadvantage of this approach is that the loop thread can not use the terminal window since the main program needs it for input from a user. If it is about logging information in the loop - then the info should be saved into a file, for example.
If you know any other solutions - please, share your experience.

0 comments:

Post a Comment