emulating `` shell operator in Python?

Richard Gruet rgruet at ina.fr
Fri Dec 3 08:53:17 EST 1999


Hi there,

I'm looking for a way to redirect stdout (and/or stderr) into a string
to emulate the Unix shell operator ``,
so that if I have a function like this one:

    def hello(): print 'hello, world'

and I call an emulated 'backquote' function like this:
    s = backquote(hello)

...I'd get the string 'hello, world' in s.

The problem is to implement the 'backquote' function. It should be able
to take args and pass them to the function:

def backquote(func, args=())

To redirect stdout and/or stderr, I could reassign sys.stdout and
sys.stderr.
I don't want to use an intermediate file, so I could use a StringIO (or
cStringIO) to avoid this.
Here is a possible implementation:

def backquotefunc(func, args=()):
 ''' Emulate the `` Unix shell operator for a function call. '''
 import sys, cStringIO
 f = cStringIO.StringIO()
 try:
  sys.stdout = f
  sys.stderr = f
  try:
   apply(func, args)
  finally:
   sys.stderr = sys.__stderr__
   sys.stdout = sys.__stdout__
  s = f.getvalue()
 finally:
  f.close()
 return s

...and it seems to work.
(some improvements could be: make stdout/stderr choice parametrable,
allow the called func
 to return its value, we then would ADD the redirected string in the
returned tuple, this way backquotefunc() would look like a specialized
call!)

- A variant accepting a Python *command* rather than a function could
be:

def backquotecmd(pyCmd):
 ''' Emulate the `` Unix shell operator for a Python command. '''
 import sys, cStringIO
 f = cStringIO.StringIO()
 try:
  sys.stdout = f
  sys.stderr = f
  try:
   exec pyCmd
  finally:
   sys.stderr = sys.__stderr__
   sys.stdout = sys.__stdout__
  s = f.getvalue()
 finally:
  f.close()
 return s

- But the really tricky case is to catch in a string the output of a
*shell* command, such as os.system('ls').
The above strategy doesnt work because the command executes in a
sub-shell (external to python) with its own stdout and stderr.

Any comment or suggestion ?
Thank you

Richard





More information about the Python-list mailing list