th0r
th0r

Reputation: 1

Issue with subprocess.check_output printing stderr, looking to implement error checking

I am trying to beautify the output of different system commands, but since I am using a non Redhat based OS my program snags executing the rpm feature. Could someone give a nudge in the right direction, I would like to make this more Pythonic and implement error checking against the rpm function if not a RH based OS.

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

traceback from Atto Allas’s code:

   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'

I have also included an image of what is currently working in my program and to better illustrate desire results, including the kernels. I hope this better helps illustrate the dilemma.
enter image description here

Upvotes: 0

Views: 537

Answers (1)

Atto Allas
Atto Allas

Reputation: 610

In my opinion, using a specific try: and except: is the most 'pythonic' way to do it. See the following example:

Replace:

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

With:

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

or alternatively,

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

Note: I do not think your code will work, but this is how you would write your code, if it were correct. Also, I cannot write this code for you, because I don't actually know what you are trying to achieve.

An example of what your code might look like is this:

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

Sample output from Windows bash terminal:

Windows bash output

Hope this helps!

Upvotes: 1

Related Questions