Each Answer to this Q is separated by one/two green lines.
What is the equivalent of the backticks found in Ruby and Perl in Python? That is, in Ruby I can do this:
foo = `cat /tmp/baz`
What does the equivalent statement look like in Python? I’ve tried
os.system("cat /tmp/baz") but that puts the result to standard out and returns to me the error code of that operation.
output = os.popen('cat /tmp/baz').read()
The most flexible way is to use the
import subprocess out = subprocess.run(["cat", "/tmp/baz"], capture_output=True) print("program output:", out)
capture_output was introduced in Python 3.7, for older versions the special function
check_output() can be used instead:
out = subprocess.check_output(["cat", "/tmp/baz"])
You can also manually construct a subprocess object if you need fine grained control:
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE) (out, err) = proc.communicate()
All these functions support keyword parameters to customize how exactly the subprocess is executed. You can for example use
shell=True to execute the program through the shell, if you need things like file name expansions of
*, but that comes with limitations.
sth is right. You can also use os.popen(), but where available (Python 2.4+) subprocess is generally preferable.
However, unlike some languages that encourage it, it’s generally considered bad form to spawn a subprocess where you can do the same job inside the language. It’s slower, less reliable and platform-dependent. Your example would be better off as:
baz is a directory and I’m trying to get the contents of all the files in that directory
? cat on a directory gets me an error.
If you want a list of files:
import os foo= os.listdir('/tmp/baz')
If you want the contents of all files in a directory, something like:
contents=  for leaf in os.listdir('/tmp/baz'): path= os.path.join('/tmp/baz', leaf) if os.path.isfile(path): contents.append(open(path, 'rb').read()) foo= ''.join(contents)
or, if you can be sure there are no directories in there, you could fit it in a one-liner:
path="/tmp/baz" foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))
foo = subprocess.check_output(["cat", "/tmp/baz"])
From Python 3.5 onward, the recommended way is to use
subprocess.run. Since Python 3.7, to get the same behaviour as you describe, you would use:
cpe = subprocess.run("ls", shell=True, capture_output=True)
This will return a
subprocess.CompletedProcess object. The output to stdout will be in
cpe.stdout, the output to stderr will be in
cpe.stderr, which will both be
bytes objects. You can decode the output to get a
str object by using
cpe.stdout.decode() or get a by passing
cpe = subprocess.run("ls", shell=True, capture_output=True, text=True)
In the latter case,
cpe.stderr are both
Easiest way is to use commands package.
import commands commands.getoutput("whoami")
import os foo = os.popen('cat /tmp/baz', 'r').read()
(6:0)$ python –version
One of the examples above is:
import subprocess proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) (out, err) = proc.communicate() print "program output:", out
For me, this failed to access the directory /tmp. After looking at the doc string for subprocess I replaced
[ “prog”, “arg”]
and got the shell expansion behavior that was desired (a la Perl’s `prog arg`)
print subprocess.Popen(“ls -ld /tmp/v*”, stdout=subprocess.PIPE, shell=True).communicate()
I quit using python a while back because I was annoyed with the difficulty of of doing the equivalent of perl `cmd …`. I’m glad to find Python has made this reasonable.
If you use subprocess.Popen, remember to specify bufsize. The default is 0, which means “unbuffered”, not “choose a reasonable default”.
This will not work in python3, but in python2 you can extend
str with a custom
__repr__ method that calls your shell command and returns it like so:
#!/usr/bin/env python import os class Command(str): """Call system commands""" def __repr__(cmd): return os.popen(cmd).read()
Which you can use like
#!/usr/bin/env python from command import Command who_i_am = `Command('whoami')` # Or predeclare your shell command strings whoami = Command('whoami') who_i_am = `whoami`