我想编写一个函数,该函数将执行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'

当前回答

拆分子进程的初始命令可能非常棘手和麻烦。

使用shlex.split()来帮助自己。

示例命令

Git log -n 5——5年前到2年前

的代码

from subprocess import check_output
from shlex import split

res = check_output(split('git log -n 5 --since "5 years ago" --until "2 year ago"'))
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

如果没有shlex.split(),代码将如下所示

res = check_output([
    'git', 
    'log', 
    '-n', 
    '5', 
    '--since', 
    '5 years ago', 
    '--until', 
    '2 year ago'
])
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

其他回答

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

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

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

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

os.remove('tmp')

这里有一个解决方案,如果你想在进程运行或不运行时打印输出。


我还添加了当前工作目录,这对我来说很有用不止一次。


希望这个解决方案能帮助到别人:)。

import subprocess

def run_command(cmd_and_args, print_constantly=False, cwd=None):
"""Runs a system command.

:param cmd_and_args: the command to run with or without a Pipe (|).
:param print_constantly: If True then the output is logged in continuous until the command ended.
:param cwd: the current working directory (the directory from which you will like to execute the command)
:return: - a tuple containing the return code, the stdout and the stderr of the command
"""
output = []

process = subprocess.Popen(cmd_and_args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)

while True:
    next_line = process.stdout.readline()
    if next_line:
        output.append(str(next_line))
        if print_constantly:
            print(next_line)
    elif not process.poll():
        break

error = process.communicate()[1]

return process.returncode, '\n'.join(output), error

在Python 3.7+中,使用subprocess.run并传递capture_output=True:

import subprocess
result = subprocess.run(['echo', 'hello', 'world'], capture_output=True)
print(repr(result.stdout))

这将返回字节:

b'hello world\n'

如果你想把字节转换成字符串,添加text=True:

result = subprocess.run(['echo', 'hello', 'world'], capture_output=True, text=True)
print(repr(result.stdout))

这将读取字节使用您的默认编码:

'hello world\n'

如果你需要手动指定不同的编码,使用encoding="your encoding"而不是text=True:

result = subprocess.run(['echo', 'hello', 'world'], capture_output=True, encoding="utf8")
print(repr(result.stdout))

可以使用以下命令运行任何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")

根据@senderle的说法,如果你像我一样使用python3.6:

def sh(cmd, input=""):
    rst = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input.encode("utf-8"))
    assert rst.returncode == 0, rst.stderr.decode("utf-8")
    return rst.stdout.decode("utf-8")
sh("ls -a")

将完全像您在bash中运行命令一样