我想编写一个函数,该函数将执行shell命令并将其输出作为字符串返回,无论它是错误消息还是成功消息。我只想得到和用命令行得到的相同的结果。

什么样的代码示例可以做到这一点呢?

例如:

def run_command(cmd):
    # ??????

print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'

当前回答

改进以获得更好的日志记录。 为了获得更好的输出,可以使用迭代器。 从下面开始,我们变得更好

from subprocess import Popen, getstatusoutput, PIPE
def shell_command(cmd):
    result = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)

    output = iter(result.stdout.readline, b'')
    error = iter(result.stderr.readline, b'')
    print("##### OutPut ###")
    for line in output:
        print(line.decode("utf-8"))
    print("###### Error ########")
    for line in error:
        print(error.decode("utf-8")) # Convert bytes to str

    status, terminal_output = run_command(cmd)
    print(terminal_output)

shell_command("ls") # this will display all the files & folders in directory

使用getstatusoutput的其他方法(容易理解)

from subprocess import Popen, getstatusoutput, PIPE

status_Code, output = getstausoutput(command)
print(output) # this will give the terminal output

# status_code, output = getstatusoutput("ls") # this will print the all files & folder available in the directory

其他回答

可以使用以下命令运行任何shell命令。我在ubuntu上使用过它们。

import os
os.popen('your command here').read()

注意:自python 2.6起已弃用。现在必须使用subprocess.Popen。下面是示例

import subprocess

p = subprocess.Popen("Your command", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")

对于相同的问题,我有一个稍微不同的需求:

捕获并返回STDOUT消息,因为它们在STDOUT缓冲区中累积(即实时)。 @vartec用python方法解决了这个问题,他使用生成器和“yield” 上面的字 打印所有STDOUT行(即使进程在STDOUT缓冲区可以完全读取之前退出) 不要浪费CPU周期以高频轮询进程 检查子流程的返回代码 如果得到非零错误返回码,则打印STDERR(与STDOUT分开)。

我综合了之前的答案,得出了以下结论:

import subprocess
from time import sleep

def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         shell=True)
    # Read stdout from subprocess until the buffer is empty !
    for line in iter(p.stdout.readline, b''):
        if line: # Don't print blank lines
            yield line
    # This ensures the process has completed, AND sets the 'returncode' attr
    while p.poll() is None:                                                                                                                                        
        sleep(.1) #Don't waste CPU-cycles
    # Empty STDERR buffer
    err = p.stderr.read()
    if p.returncode != 0:
       # The run_command() function is responsible for logging STDERR 
       print("Error: " + str(err))

这段代码的执行方式与前面的答案相同:

for line in run_command(cmd):
    print(line)

这是一个棘手但超级简单的解决方案,适用于许多情况:

import os
os.system('sample_cmd > tmp')
print(open('tmp', 'r').read())

使用命令的输出创建一个临时文件(这里是tmp),您可以从中读取所需的输出。

备注: 如果是一次性作业,可以删除tmp文件。如果需要多次执行此操作,则不需要删除tmp。

os.remove('tmp')

我也遇到了同样的问题,但我想出了一个非常简单的方法:

import subprocess
output = subprocess.getoutput("ls -l")
print(output)

注意:此解决方案是特定于Python3的subprocess.getoutput()在Python2中不起作用

就像这样:

def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while(True):
        # returns None while subprocess is running
        retcode = p.poll() 
        line = p.stdout.readline()
        yield line
        if retcode is not None:
            break

注意,我将stderr重定向到stdout,这可能不是你想要的,但我也想要错误消息。

这个函数一行一行地输出(通常你必须等待子进程完成才能得到完整的输出)。

对于你的情况,用法是:

for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):
    print line,