Призначте вихідну систему os.system змінній і не допускайте її відображення на екрані


305

Я хочу призначити результат команди, яку я запускаю за os.systemдопомогою змінної, і запобігти її виведенню на екран. Але, у наведеному нижче коді, висновок надсилається на екран, а значення, надруковане для якого, varдорівнює 0, що, напевно, означає, успішно виконана команда чи ні. Чи є спосіб призначити командний вихід змінній, а також не допустити її відображення на екрані?

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

2
можливий дублікат еквівалента Backticks в Python
msw

4
Не використовуйте os.system(ні os.popenвідповідно до прийнятої вами відповіді): використовуйте subprocess.Popen, так краще!
Алекс Мартеллі

1
@AlexMartelli, в subprocess.Popen () не можна використовувати складні команди (наприклад, трубопровідні), але з os.system можна
vak

2
@vak, звичайно, ви можете використовувати труби & c w / subprocess.Popen- просто додайте shell=True!
Алекс Мартеллі

@AlexMartelli shell=True- це взагалі дуже погана ідея! Ви повинні бути впевнені в тому, що виконуєте :)
Ignacio Fernández

Відповіді:


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рішення Вальтера ближче до однотонного пітонічного, схоже, ви шукаєте, доки вам це не цікаво 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/…
фіат

1
Додати stderr=subprocess.STDOUTдля захоплення також стандартних помилок
Dolan Antenucci

47

Модуль команд - це досить високий рівень для цього:

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

статус 0, вихід - вміст / etc / services.


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" для запуску ()
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і використав його за потребою.
Fares KA

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.