como executar um comando bash em um script python


Respostas:


15

A resposta de @ milne funciona, mas subprocess.call()fornece pouco feedback.

Eu prefiro usar subprocess.check_output()para que você possa analisar o que foi impresso no stdout:

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

check_output gera um erro na saída zero do comando chamado

Observe que isso não invoca bashou outro shell, se você não especificar o shellargumento da palavra - chave para a função (o mesmo vale para subprocess.call(), e você não deve, se não for necessário, pois impõe um risco à segurança), invoca diretamente o comando.

Se você se deparar com muitas invocações de comando (diferentes) do Python, talvez queira ver plumbum . Com isso você pode fazer o (IMO) mais legível:

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

res = sudo[apt["update"]]()
chain = echo["hello"] | cut["-c", "2-"]
chain()

É recomendável usar ( os.popenou os.system), ex res = os.popen('sudo apt update').read():? @Anthon
alper 08/08/18

1
@alper Leia 0324 python.org/dev/peps/pep-0324 . Isso explica a lógica de fazer, subprocessembora os.systeme os.popenjá existisse. Tais PEPs não são triviais para serem aceitos. Várias pessoas pensaram muito mais nisso do que você ou eu. E subprocessmelhorou desde 2003, os outros ainda estão lá para compatibilidade com versões anteriores. Você reded a os.systempágina do manual: O módulo de subprocesso fornece instalações mais poderosas para gerar novos processos e recuperar seus resultados; usar esse módulo é preferível a usar esta função.
Anthon

1
@alper Sim, você poderia. Como indiquei que é um risco potencial à segurança, não sei por que você acha que isso é recomendado. E invocar sudosó vai tornar isso mais grave. Talvez o uso de python-apt seja uma solução melhor (eu mesmo não examinei isso).
Anthon

1
@alper, nesse caso, dê uma olhada séria no prumo , vale a pena se familiarizar com isso.
Anthon

1
@alper Se você estiver no Python3, precisará fazer isso; no Python2, não. Por favor, não use os comentários aqui como um sistema de bate-papo. Se você tiver uma pergunta, publique-a como tal.
Anthon

8

É possível usar o bash como um programa, com o parâmetro -c para executar os comandos:

Exemplo:

bashCommand = "sudo apt update"
output = subprocess.check_output(['bash','-c', bashCommand])

6

O módulo do subprocesso foi projetado para fazer isso:

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

Se você deseja que o script seja encerrado se o comando falhar, considere usar em check_call()vez de analisar o código de retorno:

subprocess.check_call(["sudo", "apt", "update"])

isso me deu o seguinte rastreio: 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 (estou usando o yum como estou usando o Fedora como sistema operacional principal) #
Dremor

3
Você esqueceu os colchetes
Milind Dumbare 16/03/2015

1
Também nota que subprocess.call()está bloqueando enquanto subprocess.Popen()é sem bloqueio ..
heemayl

O que você quer dizer com "bloqueio"? @heemayl
alper

2

Também você pode usar 'os.popen'.

Exemplo:

import os

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

Resultado:

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

0

usar módulo de subprocesso

import subprocess
command = 'sudo apt update'
subprocess.check_call(command.split())

Por que estou recebendo um erro quando eu usá-lo
aquagremlin

subprocess.check_call (["sudo", "apt", "update"])
aquagremlin de

Traceback de CalledProcessError (última chamada mais recente) <ipython-input-21-33ce645708e7> em <module> () ----> 1 subprocess.check_call (["sudo", "apt", "update"]) / usr / lib / python2.7 / subprocess.pyc em check_call (* popenargs, ** kwargs) 188 se cmd for None: 189 cmd = popenargs [0] -> 190 raise CalledProcessError (retcode, cmd) 191 return 0 192 CalledProcessError: Command '[' sudo ' 'apt', 'update']' retornou código de saída diferente de zero 1
aquagremlin

Este erro só acontece quando eu executá-lo em um notebook jupyter
aquagremlin

Talvez eu vou começar uma nova pergunta uma vez que este é ot
aquagremlin
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.