views:

1731

answers:

5

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.

+25  A: 

The most flexible way is to use the subprocess module:

import subprocess

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
sth
yes, this is the only sane way, you could wrap it in a function so you can call something like execute("command")
Vinko Vrsalovic
This actually doesn't work for me, as in this case, baz is a directory and I'm trying to get the contents of all the files in that directory. (doing cat /tmp/baz/* works in ticks but not via the method described here)
Chris Bunch
re: "*" does not work; use subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) instead. Since glob (star) expansion is handled by shell, subprocessing module must use shell expansion in this case (provided by /bin/sh).
Pasi Savolainen
@Chris: You can add `shell=True` as an additional keyword parameter to the `Popen` call if you want the shell to expand the "/tmp/baz/*" parameter. This should do what you want.
sth
+1, subprocess is the preferable way to do it.
Nadia Alramli
+15  A: 
os.popen('cat /tmp/baz').read()
John Kugelman
+1  A: 
import os
foo = os.popen('cat /tmp/baz', 'r').read()
awatts
This is the equivalent of Ruby's backticks, but if your problem is to list the contents of a directory then this is not the best way to do it.
awatts
+7  A: 

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:

foo= open('/tmp/baz').read()

eta:

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))
bobince
Although this wasn't an answer to the question, it's the best answer for educating users.
noamtm
A: 

If you use subprocess.Popen, remember to specify bufsize. The default is 0, which means "unbuffered", not "choose a reasonable default".

George