0

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)

xhiro
  • 3
  • 2
  • 1
    What specific info are you trying to get? There might be an API to get it, which would totally circumvent this problem. – wjandrea Oct 06 '19 at 20:02
  • 1
    Another option is `wmic`, which can output XML: https://stackoverflow.com/a/41638971/4518341 – wjandrea Oct 06 '19 at 20:07
  • @wjandrea I don't want any particular info, otherwise i would be using a module. I just want to parse the data into a dictionary type structure. I will try to use the wmic option – xhiro Oct 06 '19 at 21:08
  • 1
    So your end goal is to learn how to parse the output? – wjandrea Oct 06 '19 at 21:10

1 Answers1

1

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' = ''
GordonAitchJay
  • 4,640
  • 1
  • 14
  • 16
  • 1
    It's worth noting this won't work if you've got wireless adapters or tunnel adapters, or if you use `ipconfig /all`. But it shouldn't take too long to modify it so it does. – GordonAitchJay Oct 07 '19 at 07:05
  • @GordanAitchJay thanks a lot I modified your code a bit, and it works perfectly! – xhiro Oct 09 '19 at 02:23