Python Forum
first try with python class, suggestion for improvement please
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
first try with python class, suggestion for improvement please
#1
Hi All,

this is my first script with python class. Thanks all forum admin.

I have few questions
1) is it good practice to have multiple class in single script?
2) how can i return converted values within class?
3) Guide me for improvement


from easysnmp import Session
import time
from datetime import datetime
import datetime
from collections import namedtuple

class fan:
    def __init__(self,host,community,version,timeout):
        self.host = host
        self.community = community
        self.version = version
        self.timeout = timeout

    def get_tmnxChassisFanSpeed(value):
        FanSpeed = { '0':'Not Applicable',
                     '1':'Unknown',
                     '2':'Half Speed',
                     '3':'Full Speed',
                     '4':'Low Speed'
                   }
        return FanSpeed.get(value,"other")
    def get_fanstatus(value):
        fanstatus = { '1':'Unknown',
                      '2':'Fan Removed',
                      '3':'Up',
                      '4':'Fail',
                      '5':'Out of Service'
                    }
        return fanstatus.get(value,"other")
 
    def get_fan_details(host):
        try:
           session = Session(hostname=host, community="cacti", version=2)

           tmnxChassisNumFanTrays = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.10')
           NumFanTrays = str(u"{value}".format(value=tmnxChassisNumFanTrays[0].value))
           tmnxChassisNumFans = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.11')
           NumFans = str(u"{value}".format(value=tmnxChassisNumFans[0].value))
           tmnxChassisFanSpeed = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.3')
           FanSpeed = str(u"{value}".format(value=tmnxChassisFanSpeed[0].value))
           tmnxChassisFanOperStatus = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.2')
           FanOperStatus = str(u"{value}".format(value=tmnxChassisFanOperStatus[0].value))
           return NumFanTrays, NumFans, FanSpeed, FanOperStatus

        except:
           print("Unable to create SNMP session with - "+host)


class Chassis:
    def __init__(self,host,community,version,timeout):
        self.host = host
        self.community = community
        self.version = version
        self.timeout = timeout
     
    def get_tmnxHwAlarmState(value):
        HwAlarmState = { '0':'Unknown',
                     '1':'Alarm Active',
                     '2':'Alarm Cleared'
                   }
        return HwAlarmState.get(value,"other")


    def get_tmnxChassisOverTempState(value):
        ChassisOverTempState = {'1':'Ok',
                                '2':'Over Temp'
                               }
        return ChassisOverTempState.get(value,"other")
    
    def cnvrt_dateTime(val1):
        date = datetime.datetime.strptime(val1, '%m%d%Y').strftime('%m/%d/%Y')
        return date


    def time_ticks_conversion(timeticks):
        converted_ticks = datetime.datetime.now() + datetime.timedelta(microseconds = int(timeticks)/10)
        return converted_ticks.strftime("%Y-%m-%d %H:%M:%S")    
    
    def conv2(data):
        Record = namedtuple('Record',
                            "year month day hour minutes seconds deciseconds "
                            "direction hoursfromutc minutesfromutc")
        L = [ord(x) for x in data]
        L[:2] = [256 * L[0] + L[1]]
        L[7] = chr(L[7])
        manfdate = Record(*L)
        manufactured_date=str(manfdate[0])+'/'+str(manfdate[1])+'/'+str(manfdate[2])+' '+str(manfdate[3])+':'+str(manfdate[4])
        return manufactured_date
 
    def get_ChassisInfo(host):
        try:
            session = Session(hostname=host, community="cacti", version=2)

            tmnxChassisTypeName = session.get('1.3.6.1.4.1.6527.3.1.2.2.1.6.1.2.20')
            ChassisTypeName = str(u"{value}".format(value=tmnxChassisTypeName.value))
            tmnxChassisNumSlots = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.7')
            ChassisNumSlots = str(u"{value}".format(value=tmnxChassisNumSlots[0].value))
            tmnxChassisNumPorts = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.8')
            ChassisNumPorts = str(u"{value}".format(value=tmnxChassisNumPorts[0].value))
            tmnxChassisOverTempState = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.24')
            ChassisOverTempState = str(u"{value}".format(value=tmnxChassisOverTempState[0].value))

            tmnxHwBaseMacAddress = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.29')
            HwBaseMacAddress = ':'.join('{:02x}'.format(ord(x)) for x in tmnxHwBaseMacAddress[0].value)
            tmnxHwMfgBoardNumber = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.4')
            HwMfgBoardNumber =  str(u"{value}".format(value=tmnxHwMfgBoardNumber[0].value))
            tmnxHwCLEI = session.walk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.11')
            HwCLEI = str(u"{value}".format(value=tmnxHwCLEI[0].value))
            tmnxHwSerialNumber = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.5')
            HwSerialNumber = str(u"{value}".format(value=tmnxHwSerialNumber[0].value))
            tmnxHwTemperature = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.18')
            HwTemperature = str(u"{value}".format(value=tmnxHwTemperature[0].value))
            tmnxHwSwLastBoot = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.22')
            HwSwLastBoot = str(u"{value}".format(value=tmnxHwSwLastBoot[0].value))
            tmnxHwAlarmState = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.24')
            HwAlarmState = str(u"{value}".format(value=tmnxHwAlarmState[0].value))

            tmnxHwManufactureDate = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.8.1.6')
            HwManufactureDate = str(u"{value}".format(value=tmnxHwManufactureDate[0].value))

            return ChassisTypeName,ChassisNumSlots,ChassisNumPorts,ChassisOverTempState,HwBaseMacAddress,HwMfgBoardNumber,\
               HwCLEI,HwSerialNumber,HwTemperature,HwSwLastBoot,HwAlarmState,HwManufactureDate
        except:
            print("Unable to create SNMP session with - "+host)

if __name__ == "__main__":
     fandetails = fan.get_fan_details('10.124.209.66')
     NumFanTrays = fandetails[0]
     NumFans = fandetails[1]
     Fanspeed = fan.get_tmnxChassisFanSpeed(fandetails[2])
     FanStatus = fan.get_fanstatus(fandetails[3])
     print('Num Of Tray:{} Number of Fans: {} Fan Speed:{} Fan Status:{}'.format(NumFanTrays,NumFans,Fanspeed,FanStatus))
     chasisdata = Chassis.get_ChassisInfo('10.124.209.66')
     print('ChassisType:{} ChassisNumSlots:{} ChassisNumPorts:{} ChassisOverTempState:{} HwBaseMacAddress:{} HwMfgBoardNumber:{} HwCLEI:{}\
            HwSerialNumber:{} HwTemperature:{} HwSwLastBoot:{} HwAlarmState:{} HwManufactureDate:{}'.format(chasisdata[0],chasisdata[1],\
            chasisdata[2],Chassis.get_tmnxChassisOverTempState(chasisdata[3]),chasisdata[4],chasisdata[5],chasisdata[6],chasisdata[7].strip(),\
            chasisdata[8],Chassis.conv2(chasisdata[9]),Chassis.get_tmnxHwAlarmState(chasisdata[10]),Chassis.cnvrt_dateTime(chasisdata[11])))
     #print(chasisdata)    
Reply
#2
(Oct-24-2019, 11:03 AM)anna Wrote: 1) is it good practice to have multiple class in single script?
2) how can i return converted values within class?
3) Guide me for improvement

1) Yes, if they are all related. For example, I have a cards.py file in my t_games project, which has two classes for different kinds of cards, a class for a deck of each of those card objects, and a class for a hand of cards. But then all of the classes for board games are in another file, and the different player classes are in a third file, and so on.

2) I'm not sure exactly what you mean, but by converted values do you mean things like get_fanstatus on line 22? If so, you can return that value into another method:

class Foo(object):

    def __init__(self, num):
        self.id = self.get_id(num)

    def get_id(self, num):
        return num + 1 * 2 ** 3
3) Here's what I noted skimming through your class, not really trying to understand what the code is doing:

3a) Comment your code. Each method or function should have a docstring explaining what it does and what it's parameters are. Each class should have a docstring explaining what it's for, what's it's methods do, and what it's attributes are for. The way I do it is like this:

class Foo(object):
    """
    A object for demostrating conversion of values. (object)

    Attributes:
    id: An ID number for the foo meeting the Scotty criteria. (int)

    Methods:
    get_id: Convert a number to a valid ID. (int)
    """

    def __init__(self, num):
        """
        Set up the foo's ID. (None)

        Parameters:
        num: The integer basis for the foo. (int)
        """
        self.id = self.get_id(num)

    def get_id(self, num):
        """
        Convert a number to a Scotty ID.  (int)

        Parameters:
        num: The base number for the Scotty ID. (int)
        """
        return num + 1 * 2 ** 3
That may seem like too much, but that's because it's just a ditzy little test class. If it still seems like too much after you do it with your code, that's because you haven't yet had to deal with other people's undocumented code. And other people includes you six months ago. Just because it's totally clear to you now doesn't mean it's totally clear to someone else or somewhen else.

In addition to the docstrings, methods longer than 4 or 5 lines, or that go through multiple steps (as you conceive steps), should have an outline of what they are doing mixed in with the code using # comments.

3b) Be consistent with your variable names. Generally you have different styles for variables, functions/methods, classes, and global constants. You see this a lot in Python: variable_names, function_names, ClassNames, CONSTANT_NAMES. That's PEP 8 style, which is common but not mandatory. However, being consistent with whatever style you use helps make the role of each name clear in the code.

3c) FanSpeed and fanstatus should be class variables. They're don't change but they are closely related to the class. I would do something like this:

class Fan:
    fan_speed = { '0':'Not Applicable',
                 '1':'Unknown',
                 '2':'Half Speed',
                 '3':'Full Speed',
                 '4':'Low Speed'
               }
    fan_status = { '1':'Unknown',
                  '2':'Fan Removed',
                  '3':'Up',
                  '4':'Fail',
                  '5':'Out of Service'
                }
                
    def __init__(self,host,community,version,timeout):
        self.host = host
        self.community = community
        self.version = version
        self.timeout = timeout

    def get_fan_speed(value):
        return self.fan_speed.get(value,"other")

    def get_fan_status(value):
        return self.fan_status.get(value,"other")
Likewise your Record namedtuple should either be a class attribute or a module level constant. As it is you are reprocessing these objects every time you call those methods. There is no need to do that.

3d) Try/except blocks should be tight and specific. Try to limit the code in the try block to just what will cause the error. If you have one or two lines to process if there is no error, they can go in there. If there's more than a couple of lines to process if there is no error, the except block should return, continue, or break, or there should be an else block for that code. The except statement should specify the specific errors you are expecting. Otherwise they might hide unexpected errors as expected errors, making it harder to debug the unexpected ones. The try/except block is especially heinous.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
thanks, some changes done

1) try/except taken out of class
2) comments are added whenever required
but getting error



from easysnmp import Session
import time
from datetime import datetime
import datetime
#from collections import namedtuple
 
class fan:
    """\
	this class to collect information about fan speed and fan status
	final output will be like below
	-------------------------------------------------------------------------------
    Environment Information

    Number of fan trays               : 1
    Number of fans                    : 3

    Fan tray number                   : 1
       Speed                           : half speed
       Status                          : up
   -------------------------------------------------------------------------------"""
	
	
	
    #convert oid number in to fan speed , str oid value
    # dict for FanSpeed oid output value	
    fan_speed =  { '0':'Not Applicable',
                  '1':'Unknown',
                  '2':'Half Speed',
                  '3':'Full Speed',
                  '4':'Low Speed'
                }
    #convert oid output in fan status, str oid value 
    #Dict for Fanstatus oid output values
    fan_status = { '1':'Unknown',
                  '2':'Fan Removed',
                  '3':'Up',
                  '4':'Fail',
                  '5':'Out of Service'
                }
       
    def __init__(self,host,community,version,timeout):
        self.host = host
        self.community = community
        self.version = version
        self.timeout = timeout

    # return fan speed and parameter will be oid value
    def get_fan_speed(value):
        return self.fan_speed.get(value,"other")
		
	#return fan status, parameter will be oid value
    def get_fan_status(value):
        return self.fan_status.get(value,"other")
 
  
    def get_fan_details(host):
           # establish easysnmp session with host
           session = Session(hostname=host, community="cacti", version=2,timeout=5)
           # start bulkwalking snmp oids 
           tmnxChassisNumFanTrays = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.10')
           NumFanTrays = str(u"{value}".format(value=tmnxChassisNumFanTrays[0].value))
           tmnxChassisNumFans = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.11')
           NumFans = str(u"{value}".format(value=tmnxChassisNumFans[0].value))
           tmnxChassisFanSpeed = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.3')
           FanSpeed = str(u"{value}".format(value=tmnxChassisFanSpeed[0].value))
           tmnxChassisFanOperStatus = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.2')
           FanOperStatus = str(u"{value}".format(value=tmnxChassisFanOperStatus[0].value))
           return NumFanTrays, NumFans, FanSpeed, FanOperStatus

if __name__ == "__main__":
        hosts = ['10.124.209.66','10.124.209.74']
        for host in hosts:
            try:
                fandetails  = fan.get_fan_details(host)
            except:
                break
            NumFanTrays = fandetails[0]
            NumFans = fandetails[1]
            Fanspeed = fan.get_fan_speed(fandetails[2])
            FanStatus = fan.get_fan_status(fandetails[3])
            print('Num Of Tray:{} Number of Fans: {} Fan Speed:{} Fan Status:{}'.format(NumFanTrays,NumFans,Fanspeed,FanStatus))
Error:
Traceback (most recent call last): File "testclas2.py", line 79, in <module> Fanspeed = fan.get_fan_speed(fandetails[2]) File "testclas2.py", line 49, in get_fan_speed return self.fan_speed.get(value,"other") NameError: name 'self' is not defined
Reply
#4
Your methods should have self as the first parameter
for example
class fan:
    ...
    ...
    def get_fan_speed(value):
        return self.fan_speed.get(value,"other")
change to
class fan:
    ...
    ...
    def get_fan_speed(self, value):
        return self.fan_speed.get(value,"other")
this also needs adding on the other methods that self is missing.
Reply
#5
anna Wrote:this is my first script with python class. Thanks all forum admin.

You've been a member of the forum for two years and started more than 60 threads but this is your first class ever! Shocked Shifty
It's high time to learn that every python object is a class instance! Write as many classes as you can!
Reply
#6
sorry.. changed as suggested.

    # return fan speed and parameter will be oid value
    def get_fan_speed(self, value):
        return self.fan_speed.get(value,"other")
         
    #return fan status, parameter will be oid value
    def get_fan_status(self, value):
        return self.fan_status.get(value,"other")
  
showing error

Error:
10.124.209.66 Traceback (most recent call last): File "testclass3.py", line 81, in <module> Fanspeed = fan.get_fan_speed(fandetails[2]) TypeError: get_fan_speed() missing 1 required positional argument: 'value'
one more query

how can I return parsed values from class, instead of calling class/function out of class

def get_fan_details(host):
           # establish easysnmp session with host
           session = Session(hostname=host, community="cacti", version=2,timeout=5)
           # start bulkwalking snmp oids 
           tmnxChassisNumFanTrays = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.10')
           NumFanTrays = str(u"{value}".format(value=tmnxChassisNumFanTrays[0].value))
           tmnxChassisNumFans = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.3.1.11')
           NumFans = str(u"{value}".format(value=tmnxChassisNumFans[0].value))
           tmnxChassisFanSpeed = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.3')
           FanSpeed = str(u"{value}".format(value=tmnxChassisFanSpeed[0].value))
           tmnxChassisFanOperStatus = session.bulkwalk('1.3.6.1.4.1.6527.3.1.2.2.1.4.1.2')
           FanOperStatus = str(u"{value}".format(value=tmnxChassisFanOperStatus[0].value))
           return NumFanTrays, NumFans, FanSpeed,FanOperStatus
instead of

Fanspeed = fan.get_fan_speed(fandetails[2])
FanStatus = fan.get_fan_status(fandetails[3])
Reply
#7
There should be an instance of the class fan created.
Try going through the class tutorials on the forum that starts with this one
[Classes] Class Basics
also the python docs class tutorial
Reply
#8
(Oct-26-2019, 09:42 AM)Yoriz Wrote: Your methods should have self as the first parameter

Sorry about that, that was an error in the code that I posted.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#9
still struggling
Reply
#10
is this way?

class host:

    fan_speed = { '0':'Not Applicable',
                  '1':'Unknown',
                  '2':'Half Speed',
                  '3':'Full Speed',
                  '4':'Low Speed'
                }
        
    fan_status = { '1':'Unknown',
                   '2':'Fan Removed',
                   '3':'Up',
                   '4':'Fail',
                   '5':'Out of Service'
                 }

   
    def __init__(self,host,community,version,timeout):
        self.host = host
        self.community = community
        self.version = version
        self.timeout = timeout
        self.fan_speed = {}
        self.fan_status = {}

    def get_fan_speed(self, value):
        return self.fan_speed.get(value,"other")
a = host('10.10.10.1','cacti',2,5)
Dict get is not correct value

Output:
print(a.get_fan_speed('2')) other
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Can you give me some suggestion about PCEP Newbie1114 0 1,025 Oct-14-2021, 03:02 PM
Last Post: Newbie1114
  instagram followers name without suggestion for you jacklee26 1 3,172 Oct-02-2021, 04:57 AM
Last Post: ndc85430
  Random coordinate generator speed improvement saidc 0 2,060 Aug-01-2021, 11:09 PM
Last Post: saidc
  Python Dev suggestion: Combining line-wrap with comments inside functions NikoNiels 2 1,737 Sep-26-2020, 07:45 PM
Last Post: bowlofred
  Function Improvement Santino 1 1,813 May-23-2020, 03:30 PM
Last Post: jefsummers
  Name Mashup Program Improvement in Python rhat398 3 2,570 Apr-05-2020, 12:09 PM
Last Post: perfringo
  Optimization suggestion Julia 2 1,737 Mar-29-2020, 12:02 PM
Last Post: Julia
  Need suggestion how to handle this error farrukh 1 2,271 Dec-21-2019, 03:21 PM
Last Post: DeaD_EyE
  Python Based Data QA Automation tool suggestion Sonia567 1 1,996 Nov-19-2019, 04:46 PM
Last Post: Larz60+
  coding improvement tips vaisesumit29 1 1,818 Mar-10-2019, 05:09 PM
Last Post: stullis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020