运行 shell 命令并捕获输出

2024-11-19 08:39:00
admin
原创
11
摘要:问题描述:我想编写一个函数来执行 shell 命令并将其输出作为字符串返回,无论它是错误还是成功消息。我只想获得与使用命令行相同的结果。什么样的代码示例可以实现这样的功能?例如:def run_command(cmd): # ?????? print run_command('mysqladmin ...

问题描述:

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

解决方案 1:

在 Python 的所有官方维护版本中,最简单的方法是使用以下subprocess.check_output函数:

>>> subprocess.check_output(['ls', '-l'])
b'total 0
-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files
'

check_output运行仅接受参数作为输入的单个程序。1它返回的结果与打印到的结果完全相同stdout。如果您需要将输入写入stdin,请跳至run或部分。如果您想执行复杂的 shell 命令,请参阅本答案末尾的Popen注释。shell=True

check_output函数适用于所有官方维护的 Python 版本。但对于较新的版本,可以使用更灵活的方法。

Python 的现代版本(3.5 或更高版本):run

如果您使用的是Python 3.5+,并且不需要向后兼容,官方文档建议在大多数任务中使用新run函数。它为模块提供了一个非常通用的高级 API subprocess。要捕获程序的输出,请将subprocess.PIPE标志传递给stdout关键字参数。然后访问stdout返回CompletedProcess对象的属性:

>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0
-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files
'

返回值是一个bytes对象,因此如果您想要一个正确的字符串,您需要decode它。假设被调用的进程返回一个 UTF-8 编码的字符串:

>>> result.stdout.decode('utf-8')
'total 0
-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files
'

如果需要的话,可以把这一切都压缩成一行:

>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0
-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files
'

如果要将输入传递给进程stdin,则可以将bytes对象传递给input关键字参数:

>>> cmd = ['awk', 'length($0) > 5']
>>> ip = 'foo
foofoo
'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=ip)
>>> result.stdout.decode('utf-8')
'foofoo
'

stderr=subprocess.PIPE您可以通过传递(捕获到result.stderr)或stderr=subprocess.STDOUTresult.stdout与常规输出一起捕获到 )来捕获错误。如果您想run在进程返回非零退出代码时抛出异常,则可以传递check=True。(或者您可以检查上面的returncode的属性result。)当安全性不是问题时,您还可以通过传递来运行更复杂的 shell 命令,shell=True如本答案末尾所述。

Python 的后续版本进一步简化了上述代码。在 Python 3.7+ 中,上面的一行代码可以拼写如下:

>>> subprocess.run(['ls', '-l'], capture_output=True, text=True).stdout
'total 0
-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files
'

run与旧方法相比,使用这种方法只会增加一点复杂性。但现在您可以run仅使用函数完成几乎所有需要做的事情。

旧版本的 Python (3-3.4):有关check_output

如果您使用的是旧版本的 Python,或者需要适度的向后兼容性,则可以使用check_output上面简要描述的函数。它从 Python 2.7 开始可用。

subprocess.check_output(*popenargs, **kwargs)  

它采用与 相同的参数Popen(见下文),并返回包含程序输出的字符串。本答案的开头有一个更详细的用法示例。在 Python 3.5+ 中,check_output相当于使用 和 执行runcheck=Truestdout=PIPE仅返回stdout属性。

您可以传递stderr=subprocess.STDOUT以确保错误消息包含在返回的输出中。当不考虑安全性时,您还可以通过传递来运行更复杂的 shell 命令,shell=True如本答案末尾所述。

如果您需要从流程中传输stderr或向流程传递输入,check_output则无法胜任这项任务。Popen在这种情况下,请参阅下面的示例。

复杂应用程序和旧版 Python(2.6 及以下版本):Popen

如果您需要深度向后兼容性,或者您需要比check_outputrun提供的更复杂的功能,您将必须直接使用Popen封装了子进程低级 API 的对象。

构造函数可以Popen接受没有参数的单个命令,或者包含命令作为其第一项的列表,后跟任意数量的参数,每个参数作为列表中的单独项。shlex.split可以帮助将字符串解析为适当格式的列表。Popen对象还接受大量不同的参数,用于进程 IO 管理和低级配置。

发送输入并捕获输出communicate几乎总是首选方法。例如:

output = subprocess.Popen(["mycmd", "myarg"], 
                          stdout=subprocess.PIPE).communicate()[0]

或者

>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, 
...                                    stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo

如果您设置了stdin=PIPEcommunicate还允许您通过以下方式将数据传递给流程stdin

>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
...                           stderr=subprocess.PIPE,
...                           stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo
foofoo
')
>>> print out
foofoo

请注意Aaron Hall 的回答,这表明在某些系统上,您可能需要将stdoutstderrstdin全部设置为PIPE(或DEVNULL)才能开始communicate工作。

在一些罕见的情况下,您可能需要复杂的实时输出捕获。Vartec的communicate答案提出了一种前进的方法,但如果使用不当,其他方法很容易陷入死锁。

与上述所有函数一样,当不担心安全性时,您可以通过传递 来运行更复杂的 shell 命令shell=True

笔记

1. 运行 shell 命令:shell=True参数

通常,每次调用runcheck_outputPopen构造函数都会执行单个程序。这意味着没有花哨的 bash 风格管道。如果您想运行复杂的 shell 命令,可以传递shell=True,这三个函数都支持。例如:

>>> subprocess.check_output('cat books/* | wc', shell=True, text=True)
' 1299377 17005208 101299376
'

但是,这样做会引发安全问题。如果您要执行的操作不仅仅是轻量级脚本,则最好分别调用每个进程,并将每个进程的输出作为下一个进程的输入,方法是

run(cmd, [stdout=etc...], input=other_output)

或者

Popen(cmd, [stdout=etc...]).communicate(other_output)

直接连接管道的诱惑非常强烈;请抵制它。否则,您可能会看到死锁或不得不做类似这样的黑客行为。

解决方案 2:

这更简单,但只适用于 Unix(包括 Cygwin)和 Python2.7。

import commands
print commands.getstatusoutput('wc -l file')

它返回一个包含(return_value,output)的元组。

对于在 Python2 和 Python3 中均有效的解决方案,请改用subprocess模块:

from subprocess import Popen, PIPE
output = Popen(["date"],stdout=PIPE)
response = output.communicate()
print response

解决方案 3:

python3优惠subprocess.getoutput()

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

解决方案 4:

类似这样的:

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,

解决方案 5:

这是一个棘手非常简单的解决方案,在许多情况下都有效:

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

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

评论中的补充说明:如果是一次性作业,您可以删除 tmp 文件。如果您需要多次执行此操作,则无需删除 tmp。

os.remove('tmp')

解决方案 6:

Vartec 的答案没有读出所有行,因此我制作了一个版本:

def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

用法与接受的答案相同:

command = 'mysqladmin create test -uroot -pmysqladmin12'.split()
for line in run_command(command):
    print(line)

解决方案 7:

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

解决方案 8:

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
'

如果希望将字节转换为字符串,请添加text=True

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

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

'hello world
'

如果您需要手动指定不同的编码,请encoding="your encoding"使用text=True

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

解决方案 9:

我对同一问题有稍许不同的感受,要求如下:

  1. 当 STDOUT 消息在 STDOUT 缓冲区中累积时,捕获并返回 STDOUT 消息(即实时)。

* *@vartec 通过使用生成器和  

上面的 'yield' 关键字以 Python 方式解决了这个问题*
  1. 打印所有 STDOUT 行(即使在 STDOUT 缓冲区完全读取之前进程就退出

  2. 不要浪费 CPU 周期来高频率轮询进程

  3. 检查子进程的返回码

  4. 如果我们得到非零错误返回代码,则打印 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)

解决方案 10:

您的里程可能会有所不同,我尝试在 Windows 上使用 Python 2.6.5 对 Vartec 的解决方案进行 @senderle 的旋转,但出现了错误,并且其他解决方案都不起作用。我的错误是:WindowsError: [Error 6] The handle is invalid

我发现我必须将 PIPE 分配给每个句柄才能使其返回我期望的输出 - 以下方法对我有用。

import subprocess

def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    return subprocess.Popen(cmd, 
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE).communicate()

并像这样调用,([0]获取元组的第一个元素,stdout):

run_command('tracert 11.1.0.1')[0]

在了解更多信息之后,我相信我需要这些管道参数,因为我正在使用不同句柄的自定义系统,所以我必须直接控制所有的 std。

要停止控制台弹出窗口(在 Windows 中),请执行以下操作:

def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    # instantiate a startupinfo obj:
    startupinfo = subprocess.STARTUPINFO()
    # set the use show window flag, might make conditional on being in Windows:
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    # pass as the startupinfo keyword argument:
    return subprocess.Popen(cmd,
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE, 
                            startupinfo=startupinfo).communicate()

run_command('tracert 11.1.0.1')

解决方案 11:

拆分初始命令可能subprocess会比较棘手且麻烦。

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

示例命令

git log -n 5 --since "5 years ago" --until "2 year ago"

代码

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
Author: Artur Barseghyan...'

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

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

解决方案 12:

这里有一个解决方案,如果您想在进程运行时打印输出,它就可以工作。


我还添加了当前工作目录,它对我很有用。


希望该解决方案能够对某人有所帮助:)。

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, '
'.join(output), error

解决方案 13:

由于某种原因,这个在 Python 2.7 上运行,您只需要导入 os!

import os 

def bash(command):
    output = os.popen(command).read()
    return output

print_me = bash('ls -l')
print(print_me)

解决方案 14:

如果您需要在多个文件上运行 shell 命令,这对我来说很有帮助。

import os
import subprocess

# Define a function for running commands and capturing stdout line by line
# (Modified from Vartec's solution because it wasn't printing all lines)
def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

# Get all filenames in working directory
for filename in os.listdir('./'):
    # This command will be run on each file
    cmd = 'nm ' + filename

    # Run the command and capture the output line by line.
    for line in runProcess(cmd.split()):
        # Eliminate leading and trailing whitespace
        line.strip()
        # Split the output 
        output = line.split()

        # Filter the output and print relevant lines
        if len(output) > 2:
            if ((output[2] == 'set_program_name')):
                print filename
                print line

编辑:刚刚看到 Max Persson 的解决方案和 JF Sebastian 的建议。我继续并采纳了这些建议。

解决方案 15:

根据@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 中运行命令完全相同

解决方案 16:

关键是使用函数subprocess.check_output

例如,以下函数捕获进程的 stdout 和 stderr 并返回该信息以及调用是否成功。它兼容 Python 2 和 3:

from subprocess import check_output, CalledProcessError, STDOUT

def system_call(command):
    """ 
    params:
        command: list of strings, ex. `["ls", "-l"]`
    returns: output, success
    """
    try:
        output = check_output(command, stderr=STDOUT).decode()
        success = True 
    except CalledProcessError as e:
        output = e.output.decode()
        success = False
    return output, success

output, success = system_call(["ls", "-l"])

如果您想将命令作为字符串而不是数组传递,请使用此版本:

from subprocess import check_output, CalledProcessError, STDOUT
import shlex

def system_call(command):
    """ 
    params:
        command: string, ex. `"ls -l"`
    returns: output, success
    """
    command = shlex.split(command)
    try:
        output = check_output(command, stderr=STDOUT).decode()
        success = True 
    except CalledProcessError as e:
        output = e.output.decode()
        success = False
    return output, success

output, success = system_call("ls -l")

解决方案 17:

改进日志记录。

为了获得更好的输出,您可以使用迭代器。从下面开始,我们变得更好

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

解决方案 18:

如果您使用subprocesspython 模块,则可以分别处理命令的 STDOUT、STDERR 和返回代码。您可以查看完整命令调用器实现的示例。当然,try..except如果您愿意,您可以对其进行扩展。

下面的函数返回 STDOUT、STDERR 和返回代码,以便您可以在其他脚本中处理它们。

import subprocess

def command_caller(command=None)
    sp = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
    out, err = sp.communicate()
    if sp.returncode:
        print(
            "Return code: %(ret_code)s Error message: %(err_msg)s"
            % {"ret_code": sp.returncode, "err_msg": err}
            )
    return sp.returncode, out, err

解决方案 19:

我想建议将simppl作为一个选项进行考虑。这是一个可通过 pypi 获得的模块:pip install simppl并在 python3 上运行。

simppl允许用户运行 shell 命令并从屏幕读取输出。

开发人员建议了三种类型的用例:

  1. 最简单的用法如下:

    from simppl.simple_pipeline import SimplePipeline
    sp = SimplePipeline(start=0, end=100):
    sp.print_and_run('<YOUR_FIRST_OS_COMMAND>')
    sp.print_and_run('<YOUR_SECOND_OS_COMMAND>') ```

  1. 要同时运行多个命令,请使用:

    commands = ['<YOUR_FIRST_OS_COMMAND>', '<YOUR_SECOND_OS_COMMAND>']
    max_number_of_processes = 4
    sp.run_parallel(commands, max_number_of_processes) ```

  1. 最后,如果您的项目使用 cli 模块,您可以直接运行另一个 command_line_tool 作为管道的一部分。另一个工具将从同一进程运行,但它将作为管道中的另一个命令从日志中显示。这使得调用其他工具的工具的调试和重构更加顺畅。

    from example_module import example_tool
    sp.print_and_run_clt(example_tool.run, ['first_number', 'second_nmber'], 
                                 {'-key1': 'val1', '-key2': 'val2'},
                                 {'--flag'}) ```

请注意,打印到 STDOUT/STDERR 是通过 python 的logging模块进行的。


下面是一个完整的代码来展示 simppl 的工作原理:

import logging
from logging.config import dictConfig

logging_config = dict(
    version = 1,
    formatters = {
        'f': {'format':
              '%(asctime)s %(name)-12s %(levelname)-8s %(message)s'}
        },
    handlers = {
        'h': {'class': 'logging.StreamHandler',
              'formatter': 'f',
              'level': logging.DEBUG}
        },
    root = {
        'handlers': ['h'],
        'level': logging.DEBUG,
        },
)
dictConfig(logging_config)

from simppl.simple_pipeline import SimplePipeline
sp = SimplePipeline(0, 100)
sp.print_and_run('ls')

解决方案 20:

这是一个简单而灵活的解决方案,可以在各种操作系统版本以及 Python 2 和 3 上使用,在 shell 模式下使用 IPython:

from IPython.terminal.embed import InteractiveShellEmbed
my_shell = InteractiveShellEmbed()
result = my_shell.getoutput("echo hello world")
print(result)

Out: ['hello world']

它有几个优点

  1. 它只需要安装 IPython,因此你在使用它时不需要担心特定的 Python 或操作系统版本,它附带了 Jupyter - 它具有广泛的支持

  2. 它默认采用一个简单的字符串 - 因此不需要使用 shell 模式参数或字符串拆分,在我看来这使得它稍微干净一些

  3. 它还可以更轻松地替换字符串中的变量甚至整个 Python 命令


为了证明:

var = "hello world "
result = my_shell.getoutput("echo {var*2}")
print(result)

Out: ['hello world hello world']

只是想给你一个额外的选择,特别是如果你已经安装了 Jupyter

当然,如果你使用的是实际的 Jupyter 笔记本而不是 .py 脚本,你也可以这样做:

result = !echo hello world
print(result)

为了达到同样的目的。

解决方案 21:

这是我用来支持 Jupyter 笔记本单元中的多线程并使单元实时打印 shell 输出的代码。它利用了bufsizestderr

from subprocess import Popen, PIPE, STDOUT

def verbosecmd(command):
    with Popen(
        command, stdout=PIPE, shell=True, stderr=STDOUT, bufsize=0, close_fds=True
    ) as process:
        for line in iter(process.stdout.readline, b""):
            print(line.rstrip().decode("utf-8"))

解决方案 22:

对于一般用途:

my_shell_command = 'grep "text" ' + filename
result = subprocess.run(my_shell_command, shell=True, text=True, capture_output=True)
print(result.stdout, end="")

解决方案 23:

乐观主义者的单行函数

def cmd(x): from subprocess import check_output as c; return c(x, shell=True, text=True) # noqa

用法

out_linux, out_win = cmd('ls -la') , cmd('ipconfig')
# ... Now go Do something with the output

解决方案 24:

如果您想要捕获 stdout 和 stderr 并显示它们,就像在交互式终端中执行 shell 命令时一样,并且您需要知道该命令的返回状态,那么您可以进行以下操作。

import time, os
cmd_str = "ls -d /bin/nonsense"

tmpfile= "/tmp/results." + str(os.getpid()) + "." + str(time.time()) 
status = os.system( cmd_str + " > " + tmpfile +" 2>&1")
with open(tmpfile, 'r') as f:
  print (f.read())
os.remove(tmpfile)
  
print("status=" + str(status))

注意:tmpfile是唯一的,使用后立即删除。Shell 用于解析 cmd_str,因此不要将此技术用于任意字符串,因为它不安全。

解决方案 25:

例如,execute('ls -ahl')区分了三/四种可能的返回值和操作系统平台:

  1. 没有输出,但运行成功

  2. 输出空行,运行成功

  3. 运行失败

  4. 输出一些内容,运行成功

下面的功能

def execute(cmd, output=True, DEBUG_MODE=False):
"""Executes a bash command.
(cmd, output=True)
output: whether print shell output to screen, only affects screen display, does not affect returned values
return: ...regardless of output=True/False...
        returns shell output as a list with each elment is a line of string (whitespace stripped both sides) from output
        could be 
        [], ie, len()=0 --> no output;    
        [''] --> output empty line;     
        None --> error occured, see below

        if error ocurs, returns None (ie, is None), print out the error message to screen
"""
if not DEBUG_MODE:
    print "Command: " + cmd

    # https://stackoverflow.com/a/40139101/2292993
    def _execute_cmd(cmd):
        if os.name == 'nt' or platform.system() == 'Windows':
            # set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instance
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        else:
            # Use bash; the default is sh
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash")

        # the Popen() instance starts running once instantiated (??)
        # additionally, communicate(), or poll() and wait process to terminate
        # communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple
        # if communicate(), the results are buffered in memory

        # Read stdout from subprocess until the buffer is empty !
        # if error occurs, the stdout is '', which means the below loop is essentially skipped
        # A prefix of 'b' or 'B' is ignored in Python 2; 
        # it indicates that the literal should become a bytes literal in Python 3 
        # (e.g. when code is automatically converted with 2to3).
        # return iter(p.stdout.readline, b'')
        for line in iter(p.stdout.readline, b''):
            # # Windows has 
, Unix has 
, Old mac has 
            # if line not in ['','
','
','
']: # Don't print blank lines
                yield line
        while p.poll() is None:                                                                                                                                        
            sleep(.1) #Don't waste CPU-cycles
        # Empty STDERR buffer
        err = p.stderr.read()
        if p.returncode != 0:
            # responsible for logging STDERR 
            print("Error: " + str(err))
            yield None

    out = []
    for line in _execute_cmd(cmd):
        # error did not occur earlier
        if line is not None:
            # trailing comma to avoid a newline (by print itself) being printed
            if output: print line,
            out.append(line.strip())
        else:
            # error occured earlier
            out = None
    return out
else:
    print "Simulation! The command is " + cmd
    print ""
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用