Присвойте вывод os.system переменной и предотвратите ее отображение на экране

305

Я хочу назначить вывод команды, которую я использую, os.systemпеременной и предотвратить ее вывод на экран. Но в приведенном ниже коде выходные данные отправляются на экран, и значение, напечатанное для, varравно 0, что, я полагаю, означает, была ли команда выполнена успешно или нет. Есть ли способ присвоить вывод команды переменной, а также остановить ее отображение на экране?

var = os.system("cat /etc/services")
print var #Prints 0
Джон
источник
2
Возможный дубликат Эквивалента Backticks в Python
MSW
4
Не используйте os.systemos.popen, согласно принятому вами ответу): используйте subprocess.Popen, это намного лучше!
Алекс Мартелли
1
@AlexMartelli, в subprocess.Popen () нельзя использовать сложные команды (например, piped), но с os.system можно
vak
2
@vak, конечно, вы можете использовать трубы и т ж subprocess.Popen- просто добавьте shell=True!
Алекс Мартелли
@AlexMartelli shell=True- (вообще) очень плохая идея! Вы должны быть очень уверены в том, что вы исполняете :)
Игнасио Фернандес

Ответы:

444

Из " Эквивалента Bash Backticks в Python ", который я давно спрашивал, вы можете использовать popen:

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

Из документов для Python 3.6 ,

Это реализовано с использованием subprocess.Popen; посмотрите документацию этого класса для более мощных способов управления и взаимодействия с подпроцессами.


Вот соответствующий код для subprocess:

import subprocess

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Крис Банч
источник
6
Обратите внимание, что subprocess.check_outputрешение Уолтера ближе к Pythonic one-liner, которое, кажется, вы ищете, если вас это не волнует stderr.
chbrown
11
@ChrisBunch Почему suprocess лучшее решение, чем os.popen?
Мартин Тома
6
Вы должны (почти) никогда не использовать shell=True. См. Docs.python.org/3/library/…
dylnmc
44
Я продолжаю сталкиваться с этим и каждый раз задаюсь вопросом - почему лучше иметь три строки сложного кода, а не одну строку очевидного кода?
Ant6n
3
Мало того, что вы (почти) никогда не должны использовать shell=True, но это также неправильно в этом случае. shell=Trueделает оболочку дочерним процессом, а не catтак, outи errявляются stdout / stderr процесса оболочки, а не catпроцесса
villapx
180

Возможно, вы также захотите взглянуть на subprocessмодуль, который был создан для замены всего семейства popenвызовов Python- типа.

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

Преимущество этого метода в том, что при вызове команд существует масса гибкости, когда соединяются стандартные потоки ввода / вывода / ошибок и т. Д.

Вальтер Мундт
источник
2
примечание, check_outputбыло добавлено с python 2.7 docs.python.org/2.7/library/…
phyatt
1
Добавьте stderr=subprocess.STDOUTтакже стандартные ошибки
Dolan
47

Модуль команд представляет собой достаточно высокоуровневый способ сделать это:

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

статус равен 0, вывод - это содержимое / etc / services.

ianmclaury
источник
43
Цитата из документации командного модуля : «Устаревшая с версии 2.6: Командный модуль был удален в Python 3. Вместо этого используйте модуль подпроцесса». ,
Кристиан Чиупиту
4
конечно, он устарел, но иногда вы просто хотите сделать что-то быстро и легко в несколько строк кода.
anon58192932
5
@advocate проверьте команду check_output подпроцесса. Это быстро, легко и не скоро обесценится!
Люк Стэнли,
29

Для python 3.5+ рекомендуется использовать функцию запуска из модуля подпроцесса . Это возвращает CompletedProcessобъект, из которого вы можете легко получить вывод, а также код возврата. Поскольку вас интересует только вывод, вы можете написать служебную оболочку, подобную этой.

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"])
Чиль тен бринке
источник
Не забывайте опцию «capture_output = True» для run ()
Elysiumplain
24

Я знаю, что на этот вопрос уже дан ответ, но я хотел бы поделиться потенциально более привлекательным способом вызова Popen с помощью from x import xфункций и:

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 года это то, что у меня сработало. Я выбросил это в отдельный файл с именем cmd.py, а затем в свой основной файл я написал from cmd import cmdlineи использовал его по мере необходимости.
Тарифы КА
1
Я получил ту же проблему с os.system, возвращающей 0, но я попробовал этот метод, и он прекрасно работает! И в качестве бонуса это выглядит красиво и аккуратно :) Спасибо!
Софи Муспратт
4

я делаю это с помощью временного файла 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-б
источник
1

Python 2.6 и 3 специально говорят, чтобы не использовать PIPE для stdout и stderr.

Правильный путь

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
Кирни Тааффе
источник