将 os.system 的输出分配给一个变量并防止它显示在屏幕上[重复]

Posted

技术标签:

【中文标题】将 os.system 的输出分配给一个变量并防止它显示在屏幕上[重复]【英文标题】:Assign output of os.system to a variable and prevent it from being displayed on the screen [duplicate] 【发布时间】:2011-03-31 01:16:31 【问题描述】:

我想将我使用os.system 运行的命令的输出分配给一个变量,并防止它输出到屏幕上。但是,在下面的代码中,输出被发送到屏幕,var 的打印值为 0,我猜这表示命令是否成功运行。有没有办法将命令输出分配给变量并阻止它显示在屏幕上?

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

【问题讨论】:

不要使用os.system(也不要使用os.popen,根据您接受的答案):使用subprocess.Popen,它方式更好! @AlexMartelli,不能在 subprocess.Popen() 中使用复杂的命令(例如管道),但是使用 os.system 可以 @vak,当然你可以使用管道 &c w/subprocess.Popen -- 只需添加shell=True @AlexMartelli shell=True (通常)是一个非常糟糕的主意!你必须非常确定你正在执行什么:) 【参考方案1】:
from os import system, remove
from uuid import uuid4

def bash_(shell_command: str) -> tuple:
    """

    :param shell_command: your shell command
    :return: ( 1 | 0, stdout)
    """

    logfile: str = '/tmp/%s' % uuid4().hex
    err: int = system('%s &> %s' % (shell_command, logfile))
    out: str = open(logfile, 'r').read()
    remove(logfile)
    return err, out

# Example: 
print(bash_('cat /usr/bin/vi | wc -l'))
>>> (0, '3296\n')```

【讨论】:

【参考方案2】:

来自我很久以前问过的“Equivalent of Bash Backticks in Python”,您可能想要使用的是popen

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

来自docs for 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

【讨论】:

请注意,Walter 的 subprocess.check_output 解决方案更接近您正在寻找的 Pythonic 单线,只要您不关心 stderr @ChrisBunch 为什么 suprocess 比 os.popen 更好? 你应该(几乎)永远不要使用shell=True。见docs.python.org/3/library/… 我不断遇到这个问题,每次我都想知道 - 为什么用三行复杂的代码比一行明显的代码更好? 您不仅(几乎)不应该使用shell=True,而且在这种情况下也是不正确的。 shell=True 使 shell 成为子进程而不是 cat,因此 outerrshell 进程的 stdout/stderr 而不是cat 进程【参考方案3】:

对于python 3.5+,建议您使用run function from the subprocess module。这将返回一个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"])

【讨论】:

不要忘记 run() 的“capture_output=True”选项 使用:result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True, shell=True, capture_output=True) 注入 capture_output 返回:ValueError: stdout and stderr arguments may not be used with capture_output.【参考方案4】:

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

【讨论】:

【参考方案5】:

我用 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

【讨论】:

【参考方案6】:

我知道这个问题已经得到解答,但我想分享一种通过使用 from x import x 和函数来调用 Popen 的可能更好看的方法:

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')

【讨论】:

3 年后,这对我有用。我把它放在一个名为cmd.py 的单独文件中,然后在我的主文件中写了from cmd import cmdline 并根据需要使用它。 我遇到了与 os.system 返回 0 相同的问题,但我尝试了这种方法,效果很好!作为奖励,它看起来又漂亮又整洁 :) 谢谢!【参考方案7】:

您可能还想查看 subprocess 模块,该模块旨在替换整个 Python 家族的 popen-type 调用。

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

它的优点是在调用命令的方式、标准输入/输出/错误流的连接位置等方面有很大的灵活性。

【讨论】:

注意,check_output 是在 python 2.7 中添加的 docs.python.org/2.7/library/… 添加stderr=subprocess.STDOUT 也可以捕获标准错误 我将此方法与 systeminfo 命令一起使用。输出是 nasty 之类的 b'\r\nHost Name: DIMUTH-LAPTOP\r\nOS Name: Microsoft Windows 10 Pro\r\nOS Version: 10.0.10240 N/A Build 10240\r\nOS Manufacturer: Microsoft Corporation 如何逐行打印。因为上面的输出是一团糟【参考方案8】:

命令模块是一种相当高级的方法:

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

status 为 0,输出为 /etc/services 的内容。

【讨论】:

引用documentation of the commands module:“自2.6版起已弃用:命令模块已在Python 3中删除。改用子进程模块。”. 确定它已经过时了,但有时您只想用几行代码快速轻松地完成某件事。 @advocate 查看子进程的 check_output 命令。它快速、简单,而且不会很快贬值!

以上是关于将 os.system 的输出分配给一个变量并防止它显示在屏幕上[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何将os.system()输出存储在python中的变量或列表中[重复]

如何将字符串列分配给变量并在 Bash 脚本的输出中引用它

将函数打印输出分配给字符串变量

T-SQL存储过程 - 无法将输出值分配给变量

输出:函数与分配给变量的函数

将shell命令的输出分配给变量[重复]