Gán đầu ra của os.system cho một biến và ngăn nó hiển thị trên màn hình


305

Tôi muốn gán đầu ra của lệnh tôi chạy bằng os.systemmột biến và ngăn không cho nó xuất ra màn hình. Nhưng, trong đoạn mã dưới đây, đầu ra được gửi đến màn hình và giá trị được in varlà 0, mà tôi đoán có nghĩa là lệnh đã chạy thành công hay chưa. Có cách nào để gán đầu ra lệnh cho biến và cũng ngăn nó hiển thị trên màn hình không?

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


4
Không sử dụng os.system(cũng không os.popen, theo câu trả lời bạn chấp nhận): sử dụng subprocess.Popen, cách đó tốt hơn!
Alex Martelli

1
@AlexMartelli, người ta không thể sử dụng một lệnh phức tạp (ví dụ: đường ống) trong quy trình con.Popen (), nhưng với os.system, người ta có thể
vak

2
@vak, tất nhiên bạn có thể sử dụng ống & c w / subprocess.Popen- chỉ cần thêm shell=True!
Alex Martelli

@AlexMartelli shell=True(nói chung) là một ý tưởng rất tồi! Bạn phải rất chắc chắn về những gì bạn đang thực hiện :)
Ignacio Fernández

Câu trả lời:


444

Từ " Tương đương của Bash Backticks trong Python ", mà tôi đã hỏi từ lâu, những gì bạn có thể muốn sử dụng là popen:

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

Từ các tài liệu cho Python 3.6 ,

Điều này được thực hiện bằng cách sử dụng sub process.Popen; xem tài liệu của lớp đó để biết các cách mạnh mẽ hơn để quản lý và giao tiếp với các quy trình con.


Đây là mã tương ứng cho subprocess:

import subprocess

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

6
Lưu ý rằng subprocess.check_outputgiải pháp của Walter gần hơn với lớp lót Pythonic mà dường như bạn đang tìm kiếm, miễn là bạn không quan tâm stderr.
chbrown

11
@ChrisBunch Tại sao suprocess là một giải pháp tốt hơn os.popen?
Martin Thoma

6
Bạn nên (gần như) không bao giờ sử dụng shell=True. Xem docs.python.org/3/library/...
dylnmc

44
Tôi tiếp tục bắt gặp điều này và mỗi khi tôi tự hỏi - tại sao tốt hơn là có ba dòng mã phức tạp thay vì một dòng mã rõ ràng?
Ant6n

3
Không chỉ bạn (hầu như) không bao giờ sử dụng shell=True, mà còn không chính xác trong trường hợp này. shell=Truelàm cho shell trở thành tiến trình con hơn là cat, vì vậy outerrlà stdout / stderr của tiến trình shell chứ không phải của catquá trình
Villapx 22/2/2017

180

Bạn cũng có thể muốn xem xét subprocessmô-đun, được xây dựng để thay thế toàn bộ các popencuộc gọi Python -type.

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

Ưu điểm của nó là có rất nhiều tính linh hoạt với cách bạn gọi các lệnh, trong đó các luồng vào / ra / lỗi tiêu chuẩn được kết nối, v.v.


2
Đáng chú ý, check_outputđã được bổ sung với python 2,7 docs.python.org/2.7/library/...
phyatt

1
Thêm vào stderr=subprocess.STDOUTđể nắm bắt các lỗi tiêu chuẩn
Dolan Antenucci

47

Mô-đun lệnh là một cách hợp lý cấp cao để làm điều này:

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

trạng thái là 0, đầu ra là nội dung của / etc / services.


43
Trích dẫn từ tài liệu của mô-đun lệnh : "Không dùng nữa kể từ phiên bản 2.6: Mô-đun lệnh đã bị xóa trong Python 3. Thay vào đó, hãy sử dụng mô-đun quy trình con." .
Cristian Ciupitu

4
chắc chắn nó đã lỗi thời nhưng đôi khi bạn chỉ muốn hoàn thành một cách nhanh chóng và dễ dàng trong một vài dòng mã.
anon58192932

5
@advocate kiểm tra lệnh checkDefput của quy trình con. Thật nhanh chóng, dễ dàng và sẽ không mất giá sớm!
Luke Stanley

29

Đối với python 3.5+, bạn nên sử dụng chức năng chạy từ mô đun quy trình con . Điều này trả về một CompletedProcessđối tượng, từ đó bạn có thể dễ dàng có được đầu ra cũng như mã trả về. Vì bạn chỉ quan tâm đến đầu ra, bạn có thể viết một trình bao bọc tiện ích như thế này.

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"])

Đừng quên tùy chọn "
captDefput

24

Tôi biết điều này đã được trả lời, nhưng tôi muốn chia sẻ một cách có khả năng tốt hơn để gọi Popen thông qua việc sử dụng from x import xvà các chức năng:

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 năm sau, đây là những gì làm việc cho tôi. Tôi đã ném nó trong một tệp riêng gọi là cmd.py, và sau đó trong tệp chính của tôi, tôi đã viết from cmd import cmdlinevà sử dụng nó khi cần thiết.
Giá vé KA

1
Tôi đã gặp vấn đề tương tự với os.system trả về 0, nhưng tôi đã thử phương pháp này và nó hoạt động rất tốt! Và như một phần thưởng, nó trông đẹp và gọn gàng :) Cảm ơn!
Sophie Muspratt

4

tôi làm điều đó với tập tin tạm thời 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 và 3 đặc biệt nói để tránh sử dụng PIPE cho thiết bị xuất chuẩn và thiết bị xuất chuẩn.

Cách chính xác là

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.