Asigne la salida de os.system a una variable y evite que se muestre en la pantalla

305

Quiero asignar la salida de un comando que ejecuto os.systema una variable y evitar que se envíe a la pantalla. Pero, en el siguiente código, la salida se envía a la pantalla y el valor impreso vares 0, lo que supongo que significa si el comando se ejecutó correctamente o no. ¿Hay alguna forma de asignar la salida del comando a la variable y también evitar que se muestre en la pantalla?

var = os.system("cat /etc/services")
print var #Prints 0
Juan
fuente
2
posible duplicado de Equivalente de Backticks en Python
msw
44
No use os.system(ni os.popen, según la respuesta que aceptó): ¡use subprocess.Popen, es mucho mejor!
Alex Martelli
1
@AlexMartelli, no se puede usar un complejo de comandos (por ejemplo, por tubería) en subprocess.Popen (), pero con os.system uno puede
vak
2
@vak, por supuesto, puedes usar tuberías & c w / subprocess.Popen- ¡solo agrega shell=True!
Alex Martelli
¡@AlexMartelli shell=Truees (generalmente) una muy mala idea! Tienes que estar muy seguro de lo que estás ejecutando :)
Ignacio Fernández

Respuestas:

444

De " Equivalente de Bash Backticks en Python ", que pregunté hace mucho tiempo, lo que es posible que desee utilizar es popen:

os.popen('cat /etc/services').read()

De los documentos para Python 3.6 ,

Esto se implementa usando subprocess.Popen; consulte la documentación de esa clase para obtener formas más potentes de administrar y comunicarse con subprocesos.


Aquí está el código correspondiente para subprocess:

import subprocess

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Chris Bunch
fuente
66
Tenga en cuenta que la subprocess.check_outputsolución de Walter está más cerca de la línea Pythonic que parece que está buscando, siempre y cuando no le importe stderr.
chbrown
11
@ChrisBunch ¿Por qué el suproceso es una mejor solución que os.popen?
Martin Thoma
66
Deberías (casi) nunca usarlo shell=True. Ver docs.python.org/3/library/…
dylnmc
44
Siempre me encuentro con esto y cada vez que me pregunto: ¿por qué es mejor tener tres líneas de código complicado en lugar de una línea de código obvio?
Ant6n
3
No solo debería (casi) nunca usar shell=True, sino que también es incorrecto en este caso. shell=Truehace que la concha el proceso hijo en lugar de cat, por lo que outy errson el stdout / stderr de la cáscara de proceso más que del catproceso
villapx
180

También es posible que desee ver el subprocessmódulo, que se creó para reemplazar toda la familia de popenllamadas de tipo Python .

import subprocess
output = subprocess.check_output("cat /etc/services", shell=True)

La ventaja que tiene es que hay una gran flexibilidad con la forma de invocar comandos, donde se conectan las secuencias estándar de entrada / salida / error, etc.

Walter Mundt
fuente
2
nota, check_outputse agregó con python 2.7 docs.python.org/2.7/library/…
phyatt
1
Agregue stderr=subprocess.STDOUTpara capturar errores estándar también
Dolan Antenucci
47

El módulo de comandos es una forma razonable de alto nivel para hacer esto:

import commands
status, output = commands.getstatusoutput("cat /etc/services")

el estado es 0, la salida es el contenido de / etc / services.

ianmclaury
fuente
43
Citando de la documentación del módulo de comandos : "Desaprobado desde la versión 2.6: El módulo de comandos se ha eliminado en Python 3. Utilice el módulo de subproceso en su lugar". .
Cristian Ciupitu
44
Seguro que está desactualizado, pero a veces solo quieres hacer algo de forma rápida y sencilla en unas pocas líneas de código.
anon58192932
55
@advocate echa un vistazo al comando check_output del subproceso. ¡Es rápido, fácil y no se depreciará pronto!
Luke Stanley
29

Para python 3.5+, se recomienda que utilice la función de ejecución desde el módulo de subproceso . Esto devuelve un CompletedProcessobjeto, desde el cual puede obtener fácilmente la salida, así como el código de retorno. Como solo le interesa el resultado, puede escribir un contenedor de utilidad como este.

from subprocess import PIPE, run

def out(command):
    result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True)
    return result.stdout

my_output = out("echo hello world")
# Or
my_output = out(["echo", "hello world"])
Chiel ten Brinke
fuente
No olvide la opción "capture_output = True" para run ()
Elysiumplain
24

Sé que esto ya ha sido respondido, pero quería compartir una forma potencialmente mejor de llamar a Popen mediante el uso de from x import xy funciones:

from subprocess import PIPE, Popen


def cmdline(command):
    process = Popen(
        args=command,
        stdout=PIPE,
        shell=True
    )
    return process.communicate()[0]

print cmdline("cat /etc/services")
print cmdline('ls')
print cmdline('rpm -qa | grep "php"')
print cmdline('nslookup google.com')
Vasili Syrakis
fuente
1
3 años después, esto es lo que funcionó para mí. Lancé esto en un archivo separado llamado cmd.py, y luego en mi archivo principal lo escribí from cmd import cmdliney lo usé según sea necesario.
Tarifas KA
1
Estaba teniendo el mismo problema con os.system devolviendo 0, pero probé este método y funciona muy bien. Y como beneficio adicional, se ve bonito y ordenado :) ¡Gracias!
Sophie Muspratt
4

lo hago con el archivo temporal os.system:

import tempfile,os
def readcmd(cmd):
    ftmp = tempfile.NamedTemporaryFile(suffix='.out', prefix='tmp', delete=False)
    fpath = ftmp.name
    if os.name=="nt":
        fpath = fpath.replace("/","\\") # forwin
    ftmp.close()
    os.system(cmd + " > " + fpath)
    data = ""
    with open(fpath, 'r') as file:
        data = file.read()
        file.close()
    os.remove(fpath)
    return data
lexa-b
fuente
1

Python 2.6 y 3 dicen específicamente que evite usar PIPE para stdout y stderr.

La forma correcta es

import subprocess

# must create a file object to store the output. Here we are getting
# the ssid we are connected to
outfile = open('/tmp/ssid', 'w');
status = subprocess.Popen(["iwgetid"], bufsize=0, stdout=outfile)
outfile.close()

# now operate on the file
Kearney Taaffe
fuente