subprocess.check_output打印stderr时出现问题,希望实现错误检查

时间:2017-12-02 06:44:37

标签: python subprocess

我正在尝试美化不同系统命令的输出,但由于我使用的是非基于Redhat的操作系统,我的程序会执行rpm功能。有人可以在正确的方向上轻推,我想让它更像Pythonic并对rpm函数实施错误检查,如果不是基于RH的操作系统。

def kernVer(kern1, kern2, kern3, kern4):
    if subprocess.check_output(["uname", "-a"]).decode('ascii').strip():
        print ('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern1) + '\x1b[0m')
    if subprocess.check_output(["uname", "-mrs"]).decode('ascii').strip():
        print ('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern2) + '\x1b[0m')
    if subprocess.check_output(["cat", "/proc/version"]).decode('ascii').strip():
        print ('\x1b[6;30;42m' + '[✔] %s' % (kern3) + '\x1b[0m')
    if subprocess.check_output(["rpm", "-q","kernel"]).decode('ascii').strip():
        print ('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern4) + '\x1b[0m')
    else:
        print ('\x1b[1;32;41m' + '[✘] Unable To Obtain Kernel Version! [✘]' + '\x1b[0m')
        return
来自Atto Allas代码的回溯:

   Traceback (most recent call last):
  File "Kern_Func_2.py", line 40, in <module>
    main()
  File "Kern_Func_2.py", line 35, in main
    kernel_info = get_kern_info()
  File "Kern_Func_2.py", line 20, in get_kern_info
    return_val = subprocess.check_output(command)
  File "/usr/lib/python3.5/subprocess.py", line 316, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.5/subprocess.py", line 383, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.5/subprocess.py", line 1289, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'cat /proc/version'

我还提供了一个当前在我的程序中工作的图像,以及更好地说明期望结果,包括内核。我希望这更有助于说明这种困境 enter image description here

1 个答案:

答案 0 :(得分:1)

在我看来,使用特定的try:except:是最“pythonic”的方式。请参阅以下示例:

替换:

if subprocess.check_output(["rpm", "-q","kernel"]).decode('ascii').strip():
    print ('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern4) + '\x1b[0m')
else:
    print ('\x1b[1;32;41m' + '[✘] Unable To Obtain Kernel Version! [✘]' + '\x1b[0m')
    return

使用:

try:
    subprocess.check_output(["rpm", "-q","kernel"]).decode('ascii').strip()
    print('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern4) + '\x1b[0m')
except subprocess.CalledProcessError:
    print('\x1b[1;32;41m' + '[✘] Unable To Obtain Kernel Version! [✘]' + '\x1b[0m')
    return

或者,

popen_check = subprocess.Popen(["rpm", "-q","kernel"])
popen_check.communicate()

if popen_check.returncode == 127: #127 is the command not found code
    print('\x1b[1;32;41m' + '[✘] Unable To Obtain Kernel Version! [✘]' + '\x1b[0m')
else:
    print('\x1b[6;30;42m' + '[✔] %s [✔]' % (kern4) + '\x1b[0m')

注意:我认为您的代码不起作用,但这就是 编写代码的方式,如果它是正确的。另外,我不能为你编写这段代码,因为我实际上并不知道你想要实现的目标。

您的代码可能的外观示例如下:

import subprocess

def get_kern_info():
    command_lists = [["uname", "-a"], ["uname", "-mrs"], ["cat /proc/version"], ["rpm", "-q","kernel"]]
    # cat is only one command because on some implementations, it breaks if the filepath is not directly in the same string as cat

    return_values = []

    for command in command_lists:
        try:
            return_val = subprocess.check_output(command)
            formatted_val = return_val.decode('ascii').strip()

            if formatted_val != '':
                return_values.append(formatted_val)
            else:
                return_values.append(str(command)+’ outputted nothing!’)

        except subprocess.CalledProcessError:
            return_values.append(str(command)+’ could not be called!’)
            continue

    return return_values

def main():
    kernel_info = get_kern_info()

    print("The data I got was: \n" + '\n'.join(kernel_info))

main()

Windows bash终端的示例输出:

Windows bash output

希望这有帮助!