Question

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.

Was it helpful?

Solution

output = os.popen('cat /tmp/baz').read()

OTHER TIPS

The most flexible way is to use the subprocess module:

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:

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))
foo = subprocess.check_output(["cat", "/tmp/baz"])

From Python 3.5 onward, the recommended way is to use subprocess.run. To get the same behaviour as you describe, you would use:

output = subprocess.run("ls", shell=True, stdout=subprocess.PIPE).stdout

This will return a bytes object. You might want to append .decode("ascii") or .decode("utf-8") to the end to get a str.

Easiest way is to use commands package.

import commands

commands.getoutput("whoami")

Output:

'bganesan'

import os
foo = os.popen('cat /tmp/baz', 'r').read()

I'm using

(6:0)$ python --version Python 2.7.1

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"]

with

"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()[0]


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`

The backtick (`) operator was removed in Python 3. It is confusingly similar to a single quote, and hard to type on some keyboards. Instead of the backtick, use the equivalent built-in function repr().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top