4
\$\begingroup\$

I'm writing a program that adds all network interfaces with multiple parameters to a list.

I have written the following code, which should work out of the box on any Linux system with Python and ethtool installed:

import imp
import os
import subprocess
import re
from enum import Enum 


class interface_type(Enum):

    OPTIC = 1
    TWISTED_PAIR = 2


class NetworkInterface:

    def set_indentifier(self, id):
        self.id = id

    def set_mac_address(self, mac):
        self.mac = mac

    def set_interface_type(self, interface_type):
        self.interface_type = interface_type


def findNetworkInterfaces(ignoredInterface):

    filteredList = netifaces.interfaces()
    network_interfaces = []

    for interface in filteredList:
        for regex in ignoredInterface:
            if re.search(regex, interface):
                break
            else:
                nwi = NetworkInterface()
                nwi.set_indentifier(interface)
                nwi.set_mac_address(setMAC(interface))
                nwi.set_interface_type(setInterfaceType(interface))
                network_interfaces.append(nwi)
                filteredList.remove(interface)
                break
    return network_interfaces


def setMAC(identifier):

    addrs = netifaces.ifaddresses(identifier)
    mac_address = addrs[netifaces.AF_LINK][0].get("addr")

    return mac_address


def setInterfaceType(identifier):

    bashCommand1 = "ethtool " + identifier 
    bashCommand2 = "grep ports"

    try:
        process1 = subprocess.Popen(bashCommand1.split(), 
            stdout=subprocess.PIPE)
        process2 = subprocess.Popen(bashCommand2.split(), 
            stdin=process1.stdout, stdout=subprocess.PIPE)
        output, error = process2.communicate()

    except:
        print ("Error determining interface type: " + error + "\n")
        print ("Interface will be treated as Optical \n")

    if "TP" in output:
        return interface_type.TWISTED_PAIR
    else: 
        return interface_type.OPTIC


if __name__ == "__main__":

    ignored_interface = ["lo", "wlp2s0"]

    try:
        imp.find_module("netifaces")
        netifaces_status = True
        import netifaces

    except ImportError as e:
        print ("netifaces not found: " + str(e))
        os.sys.exit(-1)

    network_identifiers = findNetworkInterfaces(ignored_interface)

    #print network_identifiers

    for iface in network_identifiers:
        print iface.id
        print iface.mac
        print iface.interface_type 

I'm mainly concerned with the findNetworkInterfaces function, as I feel I'm doing this in a very ineffecient way (basically copying the list and removing interfaces as to not have doubles). In this special case, I'm not concerned with PEP8 - this is something I'll do later. Any other suggestions to improve the code are very welcome.

\$\endgroup\$
5
\$\begingroup\$
  • Start writing in ;)

    End of Life for will happen pretty soon 1

  • One regex to rule them all

    Instead of looping over a the list to create a regex,

    you could use the | char which will work as an or so it can handle multiple outputs

    REGEX_FILTER = re.conmpile('lo|wlp2s0')

  • If you only need the parameters, a simple namedtuple will suffice

    You could create a namedtuple that will get rid of the empty looking class

  • IMHO setting the variables outside of the init is bad style

    I would get the different variables needed before, and only then create the NetworkInterface object.

Note I will not review getting the interface type, since I am nowhere near a linux atm

Code

from collections import namedtuple
import re

import netifaces

FILTER_REGEX = re.compile(r'lo|wlp2s0')
NetworkInterface = namedtuple('NetworkInterface', ['iface', 'mac', 'type'])

def get_mac(iface):
    addresses = netifaces.ifaddresses(iface)
    return addresses[netifaces.AF_LINK][0].get("addr")

def get_type(iface):
    """Just return TP for testing"""
    return "TP"

def find_network_interfaces():
    for iface in netifaces.interfaces():
        if FILTER_REGEX.search(iface):
            continue
        yield NetworkInterface(iface, get_mac(iface), get_type(iface))

if __name__ == '__main__':
    for nwi in find_network_interfaces():
        print(nwi.iface)
        print(nwi.mac)
        print(nwi.type)
\$\endgroup\$
  • 1
    \$\begingroup\$ Since you saved the compiled regexes to a variable, you could do FILTER_REGEX.search(iface). \$\endgroup\$ – Graipher Jan 21 at 18:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.