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

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

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.


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.


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

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')

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.