กำหนดเอาต์พุตของ os.system ให้กับตัวแปรและป้องกันไม่ให้แสดงบนหน้าจอ


305

ฉันต้องการกำหนดเอาท์พุทของคำสั่งที่ฉันเรียกใช้โดยใช้os.systemตัวแปรและป้องกันไม่ให้มันถูกส่งออกไปยังหน้าจอ แต่ในรหัสด้านล่างผลลัพธ์จะถูกส่งไปยังหน้าจอและค่าที่พิมพ์สำหรับvarคือ 0 ซึ่งฉันเดาว่าหมายถึงคำสั่งรันได้สำเร็จหรือไม่ มีวิธีใดที่จะกำหนดเอาต์พุตคำสั่งให้กับตัวแปรและหยุดมันจากการแสดงบนหน้าจอหรือไม่?

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


4
อย่าใช้os.system(หรือos.popenตามคำตอบที่คุณยอมรับ): ใช้subprocess.Popenมันเป็นวิธีที่ดีกว่า!
Alex Martelli

1
@AlexMartelli หนึ่งไม่สามารถใช้คำสั่งที่ซับซ้อน (เช่น piped) ใน subprocess.Popen () แต่ด้วย os.system หนึ่งสามารถ
vak

2
@vak แน่นอนว่าคุณสามารถใช้ pipes & c w / subprocess.Popen- เพียงเพิ่มshell=True!
Alex Martelli

@AlexMartelli shell=Trueเป็นความคิดที่แย่มาก ๆ (โดยทั่วไป)! คุณจะต้องมีมากแน่ใจว่าสิ่งที่คุณกำลังดำเนิน :)
อิกนาซิโอFernández

คำตอบ:


444

จาก " Equalent of Bash Backticks in 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แก้ปัญหาคือใกล้ชิดกับ Pythonic stderrหนึ่งซับดูเหมือนว่าคุณกำลังมองหาตราบใดที่คุณไม่สนใจเกี่ยวกับ
chbrown

11
@ChrisBunch ทำไมเป็น suprocess เป็นทางออกที่ดีกว่าos.popen?
Martin Thoma

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 -type ทั้งตระกูล

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

ข้อดีคือมีความยืดหยุ่นมากมายกับวิธีที่คุณเรียกใช้คำสั่งที่มีการเชื่อมต่อกระแสเข้า / ออก / ข้อผิดพลาดมาตรฐาน ฯลฯ


2
โน้ตcheck_outputถูกเพิ่มด้วย python 2.7 docs.python.org/2.7/library/…
phyatt

1
เพิ่มstderr=subprocess.STDOUTเพื่อจับข้อผิดพลาดมาตรฐานเช่นกัน
Dolan Antenucci

47

โมดูลคำสั่งเป็นวิธีระดับสูงที่สมเหตุสมผลในการทำสิ่งนี้:

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

สถานะคือ 0 เอาต์พุตเป็นเนื้อหาของ / etc / services


43
การอ้างอิงจากเอกสารของโมดูลคำสั่ง : "เลิกใช้แล้วตั้งแต่เวอร์ชัน 2.6: โมดูลคำสั่งถูกลบออกใน Python 3 ใช้โมดูลย่อยแทน" .
Cristian Ciupitu

4
แน่ใจว่ามันล้าสมัย แต่บางครั้งคุณแค่ต้องการทำสิ่งต่าง ๆ อย่างรวดเร็วและง่ายดายด้วยโค้ดสองสามบรรทัด
anon58192932

5
@advocate ตรวจสอบคำสั่ง check_output ของกระบวนการย่อย มันรวดเร็วง่ายและจะไม่ลดราคาเร็ว ๆ นี้!
ลุคสแตนลีย์

29

สำหรับหลาม 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" สำหรับ run ()
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และใช้งานได้ตามต้องการ
ค่าโดยสาร KA

1
ฉันได้รับปัญหาเดียวกันกับ os.system ที่ส่งคืนค่า 0 แต่ฉันลองใช้วิธีนี้และใช้งานได้ดี! และเป็นโบนัสมันดูดีและเป็นระเบียบเรียบร้อย :) ขอบคุณ!
Sophie Muspratt

4

ฉันทำกับไฟล์ temp 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.