xhiro
xhiro

Reputation: 3

Parsing Command Line Output in Windows with Python

I essentially want to get some values from a command like 'ipconfig', but when I print the output of the command I get alot of newline characters and spaces.

Code I've Tried:

>>> import subprocess
>>> output = subprocess.getstatusoutput("ipconfig")
>>> print(output)
(0, '\x0c\nWindows IP Configuration\n\n\nEthernet adapter Ethernet 2:\n\n   Media State . . . . . . . . . . . : Media disconnected\n   Connection-specific DNS Suffix  . : \n\nEthernet adapter Npcap Loopback Adapter:\n\n  
 Connection-specific DNS Suffix  . : \n   Link-local IPv6 Address . . . . . : ~e~~::7dab:~~7f:e56f:1131%9\n   Autoconfiguration IPv4 Address. . : 169.~~4.1~.49\n   
Subnet Mask . . . . . . . . . . . : 255.255.0.0\n   Default Gateway . . . . . . . . . : \n\nEthernet adapter VirtualBox Host-Only Network:\n\n   Connection-specific DNS Suffix  . : \n 
Link-local IPv6 Address . . . . . : fe80::7~~c:69aa:~~aa:~~14~10\n   IPv4 Address. . . . . . . . . . . : 192.168.~~.~\n   Subnet Mask . . . . . . . . . . . : 255.~~~.255.0\n   Default Gateway  . . . . : etc...

I'm not sure of the best way to parse this data into some sort of table with keys and values

And when trying to use code from this answer to this question here, all I could get was this error:

>>> import subprocess
>>> output = subprocess.check_output("ipconfig", shell=True)
>>> result = {}
>>> for row in output.split('\n'):
...     if ': ' in row:
...         key, value = row.split(': ')
...         result[key.strip(' .')] = value.strip()
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: a bytes-like object is required, not 'str'
>>> print(result)
{}
>>> print(result['A (Host) Record'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'A (Host) Record'

Example of what I'm looking for:

"Link-local IPv6 Address" : "my ipv6 addr"

"Subnet Mask" : "my subnet mask"

(Using python 3)

Upvotes: 0

Views: 1007

Answers (1)

GordonAitchJay
GordonAitchJay

Reputation: 4860

We get the output, decode it so it's a str, then iterate over its lines.

We'll store each separate adapter as a dict in a dict named adapters.

In the output, preceding the details of each adapter is a line starting with "Ethernet adapter ". We get the adapter's name by splicing the line from after the string "Ethernet adapter " to just before the ":" which is at index -1.

After that, it is assumed any line with " : " in it has details about the current adapter. So we split the line at " : ", clean it up a bit, and use them as key/value pairs for our current_adapter dict which we created earlier.

import subprocess

adapters = {}
output = subprocess.check_output("ipconfig").decode()

for line in output.splitlines():
    term = "Ethernet adapter "
    if line.startswith(term):
        adapter_name = line[len(term):-1]
        adapters[adapter_name] = {}
        current_adapter = adapters[adapter_name]
        continue

    split_at = " : "
    if split_at in line:
        key, value = line.split(split_at)
        key = key.replace(" .", "").strip()
        current_adapter[key] = value



for adapter_name, adapter in adapters.items():
    print(f"{adapter_name}:")
    for key, value in adapter.items():
        print(f"    '{key}' = '{value}'")
    print()

Output:

Ethernet:
    'Connection-specific DNS Suffix' = ''
    'Link-local IPv6 Address' = 'fe80::...'
    'IPv4 Address.' = '192.168.255.255'
    'Subnet Mask' = '255.255.255.255'
    'Default Gateway' = '192.168.255.255'

VMware Network Adapter VMnet1:
    'Connection-specific DNS Suffix' = ''
    'Link-local IPv6 Address' = 'fe80::...'
    'IPv4 Address.' = '192.168.255.255'
    'Subnet Mask' = '255.255.255.255'
    'Default Gateway' = ''

VMware Network Adapter VMnet8:
    'Connection-specific DNS Suffix' = ''
    'Link-local IPv6 Address' = 'fe80::...'
    'IPv4 Address.' = '192.168.255.255'
    'Subnet Mask' = '255.255.255.255'
    'Default Gateway' = ''

Upvotes: 1

Related Questions