Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the "correct" way to make a stoppable thread in Python, given stoppable pseudo-atomic units of work?

I'm writing a threaded program in Python. This program is interrupted very frequently, by user (CRTL+C) interaction, and by other programs sending various signals, all of which should stop thread operation in various ways. The thread does a bunch of units of work (I call them "atoms") in sequence.

Each atom can be stopped quickly and safely, so making the thread itself stop is fairly trivial, but my question is: what is the "right", or canonical way to implement a stoppable thread, given stoppable, pseudo-atomic pieces of work to be done?

Should I poll a stop_at_next_check flag before each atom (example below)? Should I decorate each atom with something that does the flag-checking (basically the same as the example, but hidden in a decorator)? Or should I use some other technique I haven't thought of?

Example (simple stopped-flag checking):

class stoppable(Thread):
    stop_at_next_check = False
    current_atom = None

    def __init__(self):
        Thread.__init__(self)

    def do_atom(self, atom):
        if self.stop_at_next_check:
            return False
        self.current_atom = atom
        self.current_atom.do_work()
        return True     

    def run(self):
        #get "work to be done" objects atom1, atom2, etc. from somewhere

        if not do_atom(atom1):
            return

        if not do_atom(atom2):
            return

        #...etc

    def die(self):
        self.stop_at_next_check = True
        self.current_atom.stop()
like image 580
Zac B Avatar asked Oct 29 '12 16:10

Zac B


1 Answers

Flag checking seems right, but you missed an occasion to simplify it by using a list for atoms. If you put atoms in a list, you can use a single for loop without needing a do_atom() method, and the problem of where to do the check solves itself.

def run(self):
    atoms = # get atoms
    for atom in atoms:
        if self.stop_at_next_check:
             break
        self.current_atom = atom
        atom.do_work()
like image 100
madjar Avatar answered Nov 17 '22 14:11

madjar