Tetapkan output os.system ke variabel dan mencegahnya agar tidak ditampilkan di layar

305

Saya ingin menetapkan output dari perintah yang saya jalankan gunakan os.systemuntuk variabel dan mencegahnya menjadi output ke layar. Tetapi, dalam kode di bawah ini, output dikirim ke layar dan nilai yang dicetak varadalah 0, yang saya kira menandakan apakah perintah berjalan dengan sukses atau tidak. Apakah ada cara untuk menetapkan output perintah ke variabel dan juga menghentikannya agar tidak ditampilkan di layar?

var = os.system("cat /etc/services")
print var #Prints 0
John
sumber
2
kemungkinan rangkap dari Setara Backticks dengan Python
msw
4
Jangan gunakan os.system(atau os.popen, sesuai jawaban yang Anda terima): gunakan subprocess.Popen, itu jauh lebih baik!
Alex Martelli
1
@AlexMartelli, seseorang tidak dapat menggunakan perintah kompleks (mis. Disalurkan) di subprocess.Popen (), tetapi dengan os.sistem yang dapat
vak
2
@vak, tentu saja Anda dapat menggunakan pipa & c w / subprocess.Popen- cukup tambahkan shell=True!
Alex Martelli
@AlexMartelli shell=True(umumnya) adalah ide yang sangat buruk! Anda harus sangat yakin dengan apa yang Anda jalankan :)
Ignacio Fernández

Jawaban:

444

Dari " Equivalent of Bash Backticks in Python ", yang saya tanyakan sejak lama, yang mungkin ingin Anda gunakan adalah popen:

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

Dari dokumen untuk Python 3.6 ,

Ini diimplementasikan menggunakan subproses.Popen; lihat dokumentasi kelas untuk cara yang lebih kuat untuk mengelola dan berkomunikasi dengan subproses.


Berikut kode yang sesuai untuk subprocess:

import subprocess

proc = subprocess.Popen(["cat", "/etc/services"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out
Chris Bunch
sumber
6
Perhatikan bahwa subprocess.check_outputsolusi Walter lebih dekat dengan Pythonic one-liner yang tampaknya Anda cari, selama Anda tidak peduli stderr.
chbrown
11
@ ChrisBunch. Mengapa suprocess merupakan solusi yang lebih baik os.popen?
Martin Thoma
6
Anda seharusnya (hampir) tidak pernah menggunakan shell=True. Lihat docs.python.org/3/library/…
dylnmc
44
Saya terus menemukan ini dan setiap kali saya bertanya-tanya - mengapa lebih baik memiliki tiga baris kode rumit daripada satu baris kode yang jelas?
Ant6n
3
Anda tidak hanya harus (hampir) tidak pernah menggunakan shell=True, tetapi juga salah dalam hal ini. shell=Truemenjadikan shell sebagai proses anak dan bukan cat, outdan errmerupakan stdout / stderr dari proses shell daripada catproses
villapx
180

Anda mungkin juga ingin melihat subprocessmodul, yang dibangun untuk menggantikan seluruh keluarga popenpanggilan-jenis Python .

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

Keuntungan yang dimilikinya adalah bahwa ada banyak fleksibilitas dengan cara Anda menjalankan perintah, di mana stream in / out / error standar terhubung, dll.

Walter Mundt
sumber
2
note, check_outputtelah ditambahkan dengan python 2.7 docs.python.org/2.7/library/…
phyatt
1
Tambahkan stderr=subprocess.STDOUTuntuk menangkap kesalahan standar juga
Dolan Antenucci
47

Modul perintah adalah cara tingkat tinggi yang cukup untuk melakukan ini:

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

status adalah 0, output adalah isi dari / etc / services.

ianmclaury
sumber
43
Mengutip dari dokumentasi modul perintah : "Tidak digunakan sejak versi 2.6: Modul perintah telah dihapus dengan Python 3. Gunakan modul subproses sebagai gantinya." .
Cristian Ciupitu
4
yakin itu sudah usang tetapi kadang-kadang Anda hanya ingin menyelesaikan sesuatu dengan cepat dan mudah dalam beberapa baris kode.
anon58192932
5
@advocate periksa perintah check_output dari subproses. Cepat, mudah, dan tidak akan terdepresiasi segera!
Luke Stanley
29

Untuk python 3.5+ disarankan agar Anda menggunakan fungsi run dari modul subprocess . Ini mengembalikan CompletedProcessobjek, dari mana Anda dapat dengan mudah mendapatkan output serta kode pengembalian. Karena Anda hanya tertarik pada output, Anda dapat menulis pembungkus utilitas seperti ini.

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"])
Chiel ten Brinke
sumber
Jangan lupa opsi "capture_outputput = True" untuk menjalankan ()
Elysiumplain
24

Saya tahu ini sudah dijawab, tetapi saya ingin berbagi cara yang berpotensi lebih baik untuk memanggil Popen melalui penggunaan from x import xdan fungsi:

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')
Vasili Syrakis
sumber
1
3 tahun kemudian, inilah yang berhasil bagi saya. Saya melemparkan ini di file terpisah yang disebut cmd.py, dan kemudian di file utama saya, saya menulis from cmd import cmdlinedan menggunakannya sesuai kebutuhan.
KA
1
Saya mendapatkan masalah yang sama dengan os.system yang mengembalikan 0, tetapi saya mencoba metode ini dan itu berhasil! Dan sebagai bonus itu terlihat bagus dan rapi :) Terima kasih!
Sophie Muspratt
4

saya melakukannya dengan os.system temp file:

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-b
sumber
1

Python 2.6 dan 3 secara khusus mengatakan untuk menghindari penggunaan PIPE untuk stdout dan stderr.

Cara yang benar adalah

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
Kearney Taaffe
sumber