As a System's Engineer I use Python's subprocess module quite extensively. Quite often I call to Popen using complex and long command with switches which are determined based on different conditions where the scripts is supposed to run. Hence, my Python codes will often have a similar lines to:
import subprocess as sp ... ... lookupcmd = 'lookup -C class -v variable -h %s' % host lookup = sp.Popen(lookupcmd, shell=True, stdin=sp.PIPE, stdout=sp.PIPE) ans = lookup.communicate()
This was often debugged using calls to:
or even using
import pdb; pdb.set_trace() just before
After doing this a few times for a few different tasks, I decided that enough is enough
and I am going to extend Popen to include a new keyword.
My first approach was to use that fact the
Popen is a Class which could be
inherited and extented:
import subprocess as sp class nPopen(sp.Popen): """ override the default Popen in subprocess, to allow test modus. usage: p = nPopen("ls -l", shell=True, stdout=sp.PIPE,testmode=True) will print "ls -l" and will not execute anything. This will behave as subprocess.Popen p = nPopen("ls -l", shell=True, stdout=sp.PIPE,testmode=False) print p.communicate() """ def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,testmode=False): if testmode: print args return None p = sp.Popen.__init__(self,args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags) return p
nPopen is done exactly like subprocess`s own Popen:
lsp=nPopen('ls -l', shell=True, stdout=sp.PIPE, testmode=True)
testmode=True this assignment will just print
to the standard output, and when testmode is set to
True a normal
Popen object will be created and we can use it as if we called
subprocess.Popen('ls -l', shell=True, stdout=sp.PIPE)
A second approach was suggested by kind Stackoverflow member in response to my feedback reuest.
def nPopen(*args, **kw): """ override the default Popen in subprocess, to allow test modus. usage: p = Popen("ls -l", shell=True, stdout=sp.PIPE,testmode=True) will print "ls -l" and will not execute anything. This will behave as subprocess.Popen p = Popen("ls -l", shell=True, stdout=sp.PIPE,testmode=False) p.communicate() """ dummy = False if 'testmode' in kw.keys(): dummy = kw['testmode'] del kw['testmode'] if dummy: print ''.join([repr(arg) for arg in args]) return None else: proc = sp.Popen(*args, **kw) return proc
The first approach is more sofisticated and uses the Object Oriented nature
of Python. It also requires a bit more typing, and might be harder to understand
if someone is not familiar with concepts like inheritence. The second approach
is quite simple, and provides the same interface using a bit more simple approach.
Both approaches can be reused using
from my_module import nPopen.
I installed Ubuntu 12.04 on two laptops by now. and I must rant. Ubuntu developers are assuming two many things about me. First, there is this bug, which the'migration-assitant' mounts existing partitions in READ-WRITE mode. I find it dangerous and not necessary for migration.\