2009-09-11 10 views
73

¿Cuál es el equivalente de los backticks encontrados en Ruby y Perl en Python? Es decir, en Ruby puedo hacer esto:Equivalente de Bash Backticks en Python

foo = `cat /tmp/baz` 

¿Cómo se ve la declaración equivalente en Python? Intenté os.system("cat /tmp/baz") pero eso pone el resultado en estándar y me devuelve el código de error de esa operación.

+0

http://stackoverflow.com/questions/2924310/whats-a-good-equivalent-to-pythons-subprocess-check-call-that-returns-the-conte – jfs

Respuesta

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

No estoy seguro de cómo usaría esto fuera del ejemplo del PO. Ninguna de las respuestas aquí parece abordar la pregunta pura. por ej. cómo realizar 'alguna función que da como resultado una cadena' .somemethod '' sin funciones lambda – mckenzm

+2

@mckenzm La cuestión es capturar la salida de un proceso externo Capturar la salida de una función de Python sería una pregunta bastante diferente. –

77

La forma más flexible es utilizar el módulo subprocess:

import subprocess 

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE) 
(out, err) = proc.communicate() 
print "program output:", out 

Si desea pasar la llamada a través de la carcasa, por ejemplo para conseguir la expansión nombre de archivo con *, puede utilizar el parámetro shell=True. Si usted hace esto, usted tiene que proporcionar el comando como una cadena, citado/... igual que lo escriba en el intérprete de comandos:

proc = subprocess.Popen('cat /tmp/ba* "s p a c e.txt"', shell=True, ...) 
+2

Sí, esta es la única manera correcta, podrías envolverlo en una función para que puedas llamar a algo como ejecutar ("comando") –

+0

Esto en realidad no funciona para mí, como en este caso, baz es un directorio y estoy tratando de obtener el contenido de todos los archivos en ese directorio. (haciendo cat/tmp/baz/* funciona en tics pero no a través del método descrito aquí) –

+6

re: "*" no funciona; use subprocess.Popen (["cat", "/ tmp/baz"], stdout = subprocess.PIPE, shell = True) en su lugar. Como la expansión glob (estrella) es manejada por shell, el módulo de subprocesamiento debe usar expansión de shell en este caso (provisto por/bin/sh). –

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

Esto es el equivalente a los backticks de Ruby, pero si su problema es incluir el contenido de un directorio, esta no es la mejor manera de hacerlo. – awatts

25

sth is right. También puede usar os.popen(), pero donde esté disponible (Python 2.4+) el subproceso generalmente es preferible.

Sin embargo, a diferencia de algunos idiomas que lo fomentan, generalmente se considera una mala forma generar un subproceso donde puede hacer el mismo trabajo dentro del idioma. Es más lento, menos confiable y depende de la plataforma. Su ejemplo sería mejor como:

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

eta:

Baz es un directorio y estoy tratando de conseguir el contenido de todos los archivos de ese directorio

? cat en un directorio me da un error.

Si desea una lista de archivos:

import os 
foo= os.listdir('/tmp/baz') 

Si desea que el contenido de todos los archivos en un directorio, algo así como:

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) 

o, si usted puede estar seguro de que hay no hay directorios allí, podría caber en un trazador de líneas:

path= '/tmp/baz' 
foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path)) 
+0

Aunque esta no fue una respuesta a la pregunta, es la mejor respuesta para educar a los usuarios. – noamtm

+0

El título de la pregunta es "¿Qué es el equivalente a los palos de atrás". Supuse que "gato" era solo un comando de ejemplo. Esta respuesta no ayuda con el caso general. – Jason

1

Si utiliza subproceso.Popen, recuerde especificar bufsize El valor predeterminado es 0, que significa "sin búfer", no "elegir un valor predeterminado razonable".

2

estoy usando

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

Uno de los ejemplos anteriores es:

import subprocess 
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True) 
(out, err) = proc.communicate() 
print "program output:", out 

Para yo, esto no pudo acceder al directorio/tmp.Después de mirar la cadena de documentación para el subproceso Substituí

[ "PROG", "arg"]

con

"arg prog"

y me el comportamiento de expansión de shell que se deseaba (a la 'prog arg` de Perl)

subprocess.Popen de impresión ("ls -ld/tmp/v *" True, stdout = subprocess.PIPE, shell =) .communicate() [0]


I dejar de usar pitón una mientras estaba de regreso porque estaba molesto con la dificultad de hacer el equivalente de perl `cmd ...`. Me alegra descubrir que Python ha hecho esto razonable.

14
foo = subprocess.check_output(["cat", "/tmp/baz"]) 
+0

La mejor manera de hacerlo :) – Gandaro

+3

Este es el más sencillo ahora. "subprocess.check_output" se agregó en Python 2.7, que se lanzó en julio de 2010, después de que las otras respuestas "popen" fueran g iven. –

4

La forma más fácil es utilizar el paquete de comandos.

import commands 

commands.getoutput("whoami") 

Salida:

'bganesan'

+3

Muy fácil, pero el módulo ahora está en desuso. –

1

Esto no funcionará en python3, pero en python2 se puede extender str con un __repr__ método personalizado que llama a su comando de shell y retornos es así:

#!/usr/bin/env python 

import os 

class Command(str): 
    """Call system commands""" 

    def __repr__(cmd): 
     return os.popen(cmd).read() 

Whic h se puede utilizar como

#!/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` 
+3

Además, probablemente no deberías hacer esto * – ThorSummoner

4

Desde Python 3.5 en adelante, el método recomendado es utilizar subprocess.run. Para obtener el mismo comportamiento que usted describe, se debería utilizar:

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

Esto devolverá un objeto bytes. Es posible que desee anexar .decode("ascii") o .decode("utf-8") hasta el final para obtener un str.