Назначение вывода переменной 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