Назначение вывода переменной os.system переменной и предотвращение ее отображения на экране

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

var = os.system("cat /etc/services")
print var #Prints 0

Ответ 1

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

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

Мне сказали, что subprocess - намного лучший способ решить эту проблему, поэтому вот соответствующий код:

import subprocess

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

Я знаю, что на это уже был дан ответ, но я хотел бы поделиться потенциально лучшим способом вызвать 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')

Ответ 5

Для 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"])

Ответ 6

Я делаю это с файлом temp.system temp:

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

Ответ 7

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

Ответ 8

Большое спасибо за ответы, очень полезно. Но не достаточно для получения ответа от http-сервера в моем случае Итак, я добавил "while" с тайм-аутом, например 30 секунд, после того, как запрос был выполнен системой: блокирует программу и ждет ответа HTTP, а не только результат системного вызова. Возможно, странно, но это работает!

import subprocess

# create a file object to store the output : tmp/tempfile.
cmd = "curl -X POST --data-urlencode \"parameter=" + someparametervalue + "\" http://localhost/reponse.php"
outfile = open('tmp/tempfile', 'w');
status = subprocess.Popen(cmd, bufsize=0, stdout=outfile)
outfile.close()

# wait for outfile really contains something : the response of the http server
infile = open('tmp/tempfile', 'r');
starttime = datetime.utcnow()
data=''
timeout=False
while data=='' and not timeout:
  data=infile.read()
  timeout=(datetime.utcnow()-starttime).total_seconds()>30
infile.close()

# now operate on received data