Cómo ejecutar un comando bash en un script de Python

Respuestas:

16

La respuesta de @ milne funciona, pero subprocess.call()le da pocos comentarios.

Prefiero usar subprocess.check_output()para que pueda analizar lo que se imprimió en stdout:

 import subprocess
 res = subprocess.check_output(["sudo", "apt", "update"])
 for line in res.splitlines():
     # process the output line by line

check_output arroja un error al salir en cero del comando invocado

Tenga en cuenta que esto no invoca bashu otro shell si no especifica el shellargumento de la palabra clave para la función (lo mismo es cierto para subprocess.call(), y no debería, si no es necesario, ya que impone un riesgo de seguridad), invoca directamente el mando.

Si te encuentras haciendo muchas invocaciones de comando (diferentes) de Python, es posible que desees mirar plumbum . Con eso puedes hacer la (IMO) más legible:

from plumbum.cmd import sudo, apt, echo, cut

res = sudo[apt["update"]]()
chain = echo["hello"] | cut["-c", "2-"]
chain()
Anthon
fuente
¿Se recomienda usar ( os.popeno os.system), por ejemplo res = os.popen('sudo apt update').read():? @Anthon
Alper
1
@alper Leer 0324 python.org/dev/peps/pep-0324 . Eso explica la razón de hacer subprocessaunque os.system, y os.popenya existía. Tales PEP no son triviales para ser aceptadas. Varias personas han pensado mucho más en eso de lo que tú o yo alguna vez lo haremos. Y subprocessha mejorado desde 2003, los otros todavía están allí para la compatibilidad con versiones anteriores. ¿Ha leído la os.systempágina del manual? El módulo de subprocesos proporciona instalaciones más potentes para generar nuevos procesos y recuperar sus resultados; usar ese módulo es preferible a usar esta función.
Anthon
1
@alper Sí, podrías. Como indiqué, es un peligro potencial para la seguridad, así que no sé por qué crees que se recomienda. Invocar sudosolo lo hará más severo. Quizás usar python-apt sea una mejor solución (no lo he investigado yo mismo).
Anthon
1
@alper en ese caso eche un vistazo serio al plumbum , vale la pena ponerse al día con eso.
Anthon
1
@alper Si está en Python3, debe hacerlo, en Python2 no. No utilices los comentarios aquí como un sistema de chat. Si tiene alguna pregunta, publíquela como tal.
Anthon
8

Es posible que use bash como programa, con el parámetro -c para ejecutar los comandos:

Ejemplo:

bashCommand = "sudo apt update"
output = subprocess.check_output(['bash','-c', bashCommand])
Maquinilla de afeitar
fuente
7

El módulo de subproceso está diseñado para hacer esto:

import subprocess
subprocess.call(["sudo", "apt", "update"])

Si desea que la secuencia de comandos finalice si el comando falla, puede considerar usar en check_call()lugar de analizar el código de retorno usted mismo:

subprocess.check_call(["sudo", "apt", "update"])
Milind Dumbare
fuente
esto me dio el siguiente rastreo: Traceback (most recent call last): File "/home/Dremor/test.py", line 3, in <module> subprocess.call('sudo', 'yum', 'update') File "/usr/lib64/python3.4/subprocess.py", line 537, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib64/python3.4/subprocess.py", line 767, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer (estoy usando yum como estoy usando Fedora como SO principal)
Dremor
3
Olvidaste los corchetes
Milind Dumbare
1
También tenga en cuenta que subprocess.call()está bloqueando mientras subprocess.Popen()que no está bloqueando ..
heemayl
¿Qué quieres decir con "bloqueo"? @heemayl
Alper
2

También puedes usar 'os.popen'.

Ejemplo:

import os

command = os.popen('ls -al')
print(command.read())
print(command.close())

Salida:

total 16
drwxr-xr-x 2 root root 4096 ago 13 21:53 .
drwxr-xr-x 4 root root 4096 ago 13 01:50 ..
-rw-r--r-- 1 root root 1278 ago 13 21:12 bot.py
-rw-r--r-- 1 root root   77 ago 13 21:53 test.py

None
ricardo130
fuente
0

utilizar módulo de subproceso

import subprocess
command = 'sudo apt update'
subprocess.check_call(command.split())
Fred
fuente
¿Por qué recibo un error cuando lo uso?
aquagremlin
subprocess.check_call (["sudo", "apt", "update"])
aquagremlin
CalledProcessError Traceback (última llamada más reciente) <ipython-input-21-33ce645708e7> en <module> () ----> 1 subprocess.check_call (["sudo", "apt", "update"]) / usr / lib / python2.7 / subprocess.pyc en check_call (* popenargs, ** kwargs) 188 si cmd es None: 189 cmd = popenargs [0] -> 190 raise CalledProcessError (retcode, cmd) 191 return 0 192 CalledProcessError: Command '[' sudo ',' apt ',' update ']' devolvió el estado de salida no cero 1
aquagremlin
este error solo ocurre cuando lo ejecuto en un cuaderno
jupyter
tal vez comenzaré una nueva pregunta ya que esto es ot
aquagremlin