Sunday, August 3, 2014

Python code/tip sharing starts

Welcome. The aim of this blog is for usm-ers (and beyond) to knowledge-share of tips, tricks and code based loosely around the Python programming language. The idea arose during a daily coffee-club [join us at ~10am every day], and has blossomed into a blog. Of course there are many other great python resources (e.g. stackoverflow is amazing), but I think something in-house may seem less daunting.

I've been informally learning Python mostly through 'using', and probably have many holes in my knowledge. To this end, I hope that we code share in a very open fashion. Please fell free to make suggestions to correct bugs, make generalisations, or suggest better ways of attacking the problem.

The Euclid mission uses Python as one of it's primary languages and has set style guidelines. I'd wager that it's a good idea to adopt these conventions, especially if you are a fresh convert to Python. Having said that, I don't know 1) What they are, 2) Where to find them. Anyone?

You can use the html tags < code > some code < /code > to highlight your code

Today I'll start the ball rolling, with a top-tip code snippet that I recently implemented.

Use case:

If you spawn a process (e.g. calling the command line to run some other program) and this process takes too long, you may want to kill it, and get your process back. 
In my use case, I wanted the thread to 'block' the flow of the program before continuing. 

I found the solution here:

Which worked right out of the box. I made one small addition for fun, which was to set and get the status of how the child process ran. Joerg has already kindly pointed out that I should make my status variable an instance, not a class variable [which I was actually aiming for, but failed to achieve].


#Tip1, week1 USM python club.
import threading
import subprocess

class Command1(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None
        self.status=None

    def getStatus(self):
        return self.status

    def run(self, timeout):
        self.status=0
        def target():
            print 'Thread started'
            print(self.cmd)
            self.process = subprocess.Popen(self.cmd, shell=True)
            self.process.communicate()
            self.status=1
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            self.process.terminate()
            thread.join()
            self.status=-1
        print self.process.returncode

#create the class, with some command we want to run on the command line
command = Command1("echo 'Process started'; sleep 5; echo 'Process finished'")
#call it, and tell it how long it's allowed to run before we kill it.
command.run(timeout=6)

print('should give status=1')
print(command.getStatus())

#now call it again, but this time tell it to time out after 3 secs
command.run(timeout=3)
print('should give status=-1')
print(command.getStatus())