0
class Devices:

    def __init__(self, fqdn):
        self.fqdn = fqdn

    def domain(self, fqdn):
        self.fqdn = fqdn.split(".")
        if fqdn.split(".")[1] == 'sa':
            return 'South America'
        elif fqdn.split(".")[1] == 'na':
            return 'North America'
        elif fqdn.split(".")[1] == 'ap':
            return 'Asia Pacific'
        elif fqdn.split(".")[1] == 'ea':
            return "Europe"


device_1 = Devices('retuyr.sa.abc.com')
device_2 = Devices('agtrah.na.abc.com')
domain1 = Devices('retuyr.sa.abc.com')
domain2 = Devices('agtrah.na.abc.com')

print('FQDN: %s' % device_1.fqdn)
print('Region is: %s' % domain1.domain(fqdn='retuyr.sa.abc.com'))
print('FQDN: %s' % device_2.fqdn)
print('Region is: %s' % domain2.domain(fqdn='agtrah.na.abc.com'))

I know there could be other ways to find the region here and it is not necessary to do a 'split'. But, I have got some other functions to run in child classes so need to keep it this way.

and the output here is:

FQDN: retuyr.sa.abc.com
Region is: South America
FQDN: agtrah.na.abc.com
Region is: North America

Now, I was able to do this much. But, what I want is to read a particular column from csv file, that has FQDN name and iterate over all the names in that file. The csv file has many columns in it and it is a very large file. How shall i parse those value inside this class. Please help!

EDIT:

My CSV looks like this:

Server, FQDN, IP_Address, Name, primary1, Address
abc1, retuyr.sa.abc.com, 10.10.10.1, someinfo, someaddress
abc1, agtrah.na.abc.com, 10.10.10.2, someinfo, someaddress
xyz2, somemorefqdns, 10.10.10.3, someinfo, someaddress
...
...

This is a pretty big csv file. but what I'm concerned here is, to only get the FQDN and get the desired region, based on my FOR loop conditions. My desired output will remain the same. Only difference is, I don't want to enter all these FQDN names manually. Just want them to read it from the csv file.

Karan M
  • 309
  • 2
  • 17
  • can you edit your question to include sample data of the csv? also include the headers of the column and your desired output. – MooingRawr Jun 20 '18 at 13:44
  • 1
    Give this a read too it should do what you want it to https://stackoverflow.com/questions/16503560/read-specific-columns-from-a-csv-file-with-csv-module – MooingRawr Jun 20 '18 at 14:28

1 Answers1

2

Using pandas as suggested in the post referenced by MooingRawr is one solution, the other is to just use the builtin csv.DictReader.

Also, it seems terribly counterproductive to initialize a class instance with one attribute value, just to overwrite it immediately with the value you actually want. I also don't believe it's good practice to drastically change what the type of that attribute is. If the initial attribute value is irrelevant, then you could keep the method as a class method instead.

Additionally, I find dictionaries for lookups to be more concise and easier to maintain than long if-statements.

import csv

DOMAINLOOKUP = {
    'sa': 'South America',
    'na': 'North America',
    'ap': 'Asia Pacific',
    'ea': "Europe",
}

class Devices():
    def __init__(self,fqdn):
        self.fqdn = fqdn

    @property
    def fqdnparts(self):
        """ Returns the fqdn split into its individual components (dot delineated) """
        ## In your original code, calling domain replaced the self.fqdn
        ## string with a list, thus making it impossible to predict the type
        ## of fqdn on any given object, so I created a new attribute to
        ## interface with the split value
        return self.fqdn.split(".")

    @property
    def domain(self):
        code = self.fqdnparts[1]
        return DOMAINLOOKUP[code]

def initializefile(file):
    with open(file) as f:
        return convertrows(csv.DictReader(f))

def convertrows(rows):
    return [Devices(row['FQDN']) for row in rows]

file = r"My\file.csv"
devices = initializefile(file)

for device in devices:
    print(f"FDQN: {device.fqdn}, Region: {device.domain}")
## Prints
## > "FDQN: retuyr.sa.abc.com, Region: South America"
## > "FDQN: agtrah.na.abc.com, Region: North America"
Reid Ballard
  • 1,480
  • 14
  • 19
  • Can you please explain me '@property'? I have just started learning OOP concepts in Python and I presume it's a class method. But what exactly it is doing in this code? This could be a very good example for me to understand more about it. – Karan M Jun 21 '18 at 01:18
  • 1
    The `@`-symbol denotes a decorator. `property` is a function which can be used as a decorator. Here's a [comprehensive answer](https://stackoverflow.com/a/17330273/3225832) to save me room in the comments. I kind of misspoke when I referenced "classmethod" above; as it so happens, `classmethod` is another decorating function, but I meant to say a class function (in other words, a function defined on `Devices`). I personally think it's better to just have it as an instance method, and I decorated it and `fqdnparts` with `property` because they act more like attributes than methods. – Reid Ballard Jun 21 '18 at 01:35
  • 1
    I'm 90% sure [this is the tutorial](http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/) I first read to understand decorators. If that one seems too dense, I [skimmed over this one](https://realpython.com/primer-on-python-decorators/) and it looks like it hits the main points. – Reid Ballard Jun 21 '18 at 01:42
  • This helped to clarify lot of things regarding decorators. And for example, let's say if i wanted to return not just 'FQDN' row but also 'IP Address'. Then will this 'return [Devices(row['FQDN']) for row in rows]' change to 'return [Devices(row['FQDN'], ['IP Address']) for row in rows]' ? Basically, that was one more thing i wanted to clarify, lets suppose if I want to read multiple columns of my choice. – Karan M Jun 21 '18 at 14:02
  • 1
    Each [row is a dict](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) , so you'll just access the value for each column name you want to include (in otherwords: `return [Devices(row['FQDN'], row['IP Address']) for row in rows]`). You'll also need to update your class to accept the new arguments: `def __init__(self, fqdn, ipaddress): [...etc...] self.ipaddress = ipaddress` – Reid Ballard Jun 21 '18 at 14:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173578/discussion-between-karan-m-and-reid-ballard). – Karan M Jun 21 '18 at 17:54