3

I'm not a Perl user, but from this question deduced that it's exceedingly easy to retrieve the standard output of a program executed through a Perl script using something akin to:

$version = `java -version`;  

How would I go about getting the same end result in Python? Does the above line retrieve standard error (equivalent to C++ std::cerr) and standard log (std::clog) output as well? If not, how can I retrieve those output streams as well?

Thanks, Geoff

2
  • no, perl intentionally does not include stderr (unless you redirect it in your command like 2>&1). No idea how C++'s std::clog acts; that's not afaik something provided by the parent process. Commented May 10, 2010 at 17:36
  • 1
    related question: stackoverflow.com/questions/236737/… Commented May 11, 2010 at 8:24

3 Answers 3

7

For python 2.5: sadly, no. You need to use subprocess:

import subprocess
proc = subprocess.Popen(['java', '-version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()

Docs are at http://docs.python.org/library/subprocess.html

Sign up to request clarification or add additional context in comments.

3 Comments

I should have specified Python 3, but it doesn't seem to make a difference in this case. :) Thanks!
I don't know why you think this is so sad. I generally find that Perl code which is littered with backtick expressions is of very poor quality and dubious security and robustness.
Because it shouldn't require ~100 characters of pure boilerplate to do something as absolutely ubiquitous in a scripting language as making a system call and getting the output, and I shouldn't have to roll my own. (That being said, python has replaced perl as my this-just-got-too-complicated-for-grep-and-sed language in the past couple of years. Typically, I'm entirely unconcerned about security and robustness when using it, which makes your take -- while probably useful to someone doing production work with it -- unconvincing for me.)
6

In Python 2.7+

from subprocess import check_output as qx

output = qx(['java', '-version'])

The answer to Capturing system command output as a string question has implementation for Python < 2.7.

Comments

4

As others have mentioned you want to use the Python subprocess module for this.

If you really want something that's more succinct you can create a function like:

#!/usr/bin/env python 
import subprocess, shlex

def captcmd(cmd):
    proc = subprocess.Popen(shlex.split(cmd), \
      stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)

    out, err = proc.communicate()
    ret = proc.returncode
    return (ret, out, err)

... then you can call that as:

ok, o, e = captcmd('ls -al /foo /bar ...')
print o
if not ok:
    print >> sys.stderr, "There was an error (%d):\n" % ok
    print >> sys.stderr, e

... or whatever.

Note: I'm using shlex.split() as a vastly safer alternative to shell=True

Naturally you could write this to suit your own tastes. Of course for every call you have to either provide three names into which it can unpack the result tuple or you'd have to pull the desired output from the result using normal indexing (captcmd(...)[1] for the output, for example). Naturally you could write a variation of this function to combine stdout and stderr and to discard the result code. Those "features" would make it more like the Perl backtick expressions. (Do that and take out the shlex.split() call and you have something that's as crude and unsafe as what Perl does, in fact).

2 Comments

Could you elaborate on the safety implications of not using shlex.split()?
@Tim: Passing unparsed strings to a shell running in a subprocess leaves open a number of possible attacks (and parsing bugs) which are not exploitable when passing a vector of command + arguments to the execve system call. shlex.split() parses a normal shell command into a vector for you. For example consider the string: 'uname -r $(touch ~/flag)' ... pass it to Popen with shell=True and you've been p0wn3d, split it into a vector and pass it to Popen with shell=False and you get an error (extra argument to the uname command. There are many ways to trick side effects into a shell command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.