From ericlake at gmail.com Wed Jul 9 16:23:19 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 10:23:19 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) Message-ID: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> I am trying to write a script that I can use to gather information about the windows servers we have in our network. I started off with it being just a procedural script and I am now trying to put all of the functions in a class. This is still very much a work in progress. What can I do to improve on this / make it work? Any help would be appreciated. When I run the following from ipython to test it against my local machine I get this output: In [64]: server = diskspace.SysInfo('localhost') In [65]: server.GetLocalDrives() --------------------------------------------------------------------------- TypeError Traceback (most recent call last) C:\Documents and Settings\elake\Desktop\ in () TypeError: GetLocalDrives() takes no arguments (1 given) import sys import wmi class SysInfo(object): def __init__(self, hostname): self.host = hostname server = wmi.WMI(self.host) def GetLocalDrives(): driveList = [] for disk in self.Win32_LogicalDisk(): if disk.DriveType == 3: driveList.append(str(disk.Name)) return driveList def GetTotalDiskSize(drive): for disk in server.Win32_LogicalDisk(): if disk.Name == drive: total = long(disk.Size) /1073741824.0 return total def GetFreeDiskSpace(drive): for disk in server.Win32_LogicalDisk(): if disk.Name == drive: free = long(disk.FreeSpace) /1073741824.0 return free def GetUsedDiskSpace(drive): total = GetTotalDiskSpace(drive) free = GetTotalDiskSpace(drive) used = (total - free) return used def GetStorage(self): server = wmi.WMI(self.host) print "Gather information on %s\n" % self.host outfile.write("%s ::\n" % self.host) for disk in server.Win32_LogicalDisk(): if disk.DriveType == 3: total = long(disk.Size) /1073741824.0 free = long(disk.FreeSpace) /1073741824.0 used = (total - free) per_used = (used * 100) / total outfile.write("\tDrive %s\n" % disk.Name) outfile.write("\t\tTotal Size: %3.2f GB\n" % total) outfile.write("\t\tFree Space: %3.2f GB\n" % free) outfile.write("\t\tUsed Space: %3.2f GB\n" % used) outfile.write('\t\tPercent Used: %.2f \n' % per_used) def GetNodeName(): for os in server.Win32_OperatingSystem(): activeNode = server.CSName return activeNode if __name__ == '__main__': infile = open('san.txt', 'r') outfile = open('test4.txt', 'w') for host in infile.readlines(): host = host.strip() try: server = SysInfo(host) server.GetStorage() outfile.write("\n") except KeyboardInterrupt: print "The user canceled the job.\n" sys.exit(0) except: outfile.write("%s does not appear to be available.\n\n" % host) print "Done!\n" infile.close() outfile.close() -- Thanks, Eric Lake From ericlake at gmail.com Wed Jul 9 16:55:32 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 10:55:32 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> Message-ID: <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> The output above was from a run of the script with GetLocalDrives(self) set. I had to change it to the following to make it work: import sys import wmi class SysInfo(object): def __init__(self, hostname): self.host = hostname def GetLocalDrives(self): server = wmi.WMI(self.host) driveList = [] for disk in server.Win32_LogicalDisk(): if disk.DriveType == 3: driveList.append(str(disk.Name)) return driveList I would like to not have to do 'server = wmi.WMI(self.host)' in every method. Once I call mach = diskspace.SysInfo('localhost') I would like the wmi stuff to be set. On Wed, Jul 9, 2008 at 10:26 AM, Sam Corder wrote: > Change def GetLocalDrives() > to > def GetLocalDrives(self) > and it will work. All methods attached to an instance of a class need to take self as the first parameter. > > ----- Original Message ----- > From: Eric Lake > To: centraloh at python.org > Sent: Wednesday, July 9, 2008 10:23:19 AM GMT-0500 Auto-Detected > Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) > > I am trying to write a script that I can use to gather information > about the windows servers we have in our network. I started off with > it being just a procedural script and I am now trying to put all of > the functions in a class. This is still very much a work in progress. > What can I do to improve on this / make it work? Any help would be > appreciated. When I run the following from ipython to test it against > my local machine I get this output: > > In [64]: server = diskspace.SysInfo('localhost') > > In [65]: server.GetLocalDrives() > --------------------------------------------------------------------------- > TypeError Traceback (most recent call last) > > C:\Documents and Settings\elake\Desktop\ in () > > TypeError: GetLocalDrives() takes no arguments (1 given) > > > > import sys > import wmi > > class SysInfo(object): > def __init__(self, hostname): > self.host = hostname > server = wmi.WMI(self.host) > > def GetLocalDrives(): > driveList = [] > for disk in self.Win32_LogicalDisk(): > if disk.DriveType == 3: > driveList.append(str(disk.Name)) > return driveList > > def GetTotalDiskSize(drive): > for disk in server.Win32_LogicalDisk(): > if disk.Name == drive: > total = long(disk.Size) /1073741824.0 > return total > > def GetFreeDiskSpace(drive): > for disk in server.Win32_LogicalDisk(): > if disk.Name == drive: > free = long(disk.FreeSpace) /1073741824.0 > return free > > def GetUsedDiskSpace(drive): > total = GetTotalDiskSpace(drive) > free = GetTotalDiskSpace(drive) > used = (total - free) > return used > > def GetStorage(self): > server = wmi.WMI(self.host) > print "Gather information on %s\n" % self.host > outfile.write("%s ::\n" % self.host) > for disk in server.Win32_LogicalDisk(): > if disk.DriveType == 3: > total = long(disk.Size) /1073741824.0 > free = long(disk.FreeSpace) /1073741824.0 > used = (total - free) > per_used = (used * 100) / total > outfile.write("\tDrive %s\n" % disk.Name) > outfile.write("\t\tTotal Size: %3.2f GB\n" % total) > outfile.write("\t\tFree Space: %3.2f GB\n" % free) > outfile.write("\t\tUsed Space: %3.2f GB\n" % used) > outfile.write('\t\tPercent Used: %.2f \n' % per_used) > > def GetNodeName(): > for os in server.Win32_OperatingSystem(): > activeNode = server.CSName > return activeNode > > if __name__ == '__main__': > > infile = open('san.txt', 'r') > outfile = open('test4.txt', 'w') > > for host in infile.readlines(): > host = host.strip() > try: > server = SysInfo(host) > server.GetStorage() > outfile.write("\n") > except KeyboardInterrupt: > print "The user canceled the job.\n" > sys.exit(0) > except: > outfile.write("%s does not appear to be available.\n\n" % host) > > print "Done!\n" > > infile.close() > outfile.close() > > -- > Thanks, > > Eric Lake > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > http://mail.python.org/mailman/listinfo/centraloh > > -- Thanks, Eric Lake From ericlake at gmail.com Wed Jul 9 17:14:43 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 11:14:43 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> Message-ID: <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> That seems to be the fix there. If I have something like the following: def GetTotalDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: total = long(disk.Size) /1073741824.0 return total def GetFreeDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: free = long(disk.FreeSpace) /1073741824.0 return free def GetUsedDiskSpace(self, drive): self.drive = drive total = GetTotalDiskSpace(self.drive) free = GetTotalDiskSpace(self.drive) used = (total - free) return used should I change the: total = GetTotalDiskSpace(self.drive) to total = self.GetTotalDiskSpace(self.drive) On Wed, Jul 9, 2008 at 11:07 AM, Steven Huwig wrote: > How about putting initialization code in the __init__ method instead? > > def __init__(self, hostname): > self.host = hostname > self.server = wmi.WMI(self.host) > > and replace all references to server with self.server . > > > On Wed, Jul 9, 2008 at 10:55 AM, Eric Lake wrote: >> The output above was from a run of the script with >> GetLocalDrives(self) set. I had to change it to the following to make >> it work: >> >> import sys >> import wmi >> >> class SysInfo(object): >> def __init__(self, hostname): >> self.host = hostname >> >> def GetLocalDrives(self): >> server = wmi.WMI(self.host) >> driveList = [] >> for disk in server.Win32_LogicalDisk(): >> if disk.DriveType == 3: >> driveList.append(str(disk.Name)) >> return driveList >> >> I would like to not have to do 'server = wmi.WMI(self.host)' in every >> method. Once I call mach = diskspace.SysInfo('localhost') I would like >> the wmi stuff to be set. >> >> On Wed, Jul 9, 2008 at 10:26 AM, Sam Corder wrote: >>> Change def GetLocalDrives() >>> to >>> def GetLocalDrives(self) >>> and it will work. All methods attached to an instance of a class need to take self as the first parameter. >>> >>> ----- Original Message ----- >>> From: Eric Lake >>> To: centraloh at python.org >>> Sent: Wednesday, July 9, 2008 10:23:19 AM GMT-0500 Auto-Detected >>> Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) >>> >>> I am trying to write a script that I can use to gather information >>> about the windows servers we have in our network. I started off with >>> it being just a procedural script and I am now trying to put all of >>> the functions in a class. This is still very much a work in progress. >>> What can I do to improve on this / make it work? Any help would be >>> appreciated. When I run the following from ipython to test it against >>> my local machine I get this output: >>> >>> In [64]: server = diskspace.SysInfo('localhost') >>> >>> In [65]: server.GetLocalDrives() >>> --------------------------------------------------------------------------- >>> TypeError Traceback (most recent call last) >>> >>> C:\Documents and Settings\elake\Desktop\ in () >>> >>> TypeError: GetLocalDrives() takes no arguments (1 given) >>> >>> >>> >>> import sys >>> import wmi >>> >>> class SysInfo(object): >>> def __init__(self, hostname): >>> self.host = hostname >>> server = wmi.WMI(self.host) >>> >>> def GetLocalDrives(): >>> driveList = [] >>> for disk in self.Win32_LogicalDisk(): >>> if disk.DriveType == 3: >>> driveList.append(str(disk.Name)) >>> return driveList >>> >>> def GetTotalDiskSize(drive): >>> for disk in server.Win32_LogicalDisk(): >>> if disk.Name == drive: >>> total = long(disk.Size) /1073741824.0 >>> return total >>> >>> def GetFreeDiskSpace(drive): >>> for disk in server.Win32_LogicalDisk(): >>> if disk.Name == drive: >>> free = long(disk.FreeSpace) /1073741824.0 >>> return free >>> >>> def GetUsedDiskSpace(drive): >>> total = GetTotalDiskSpace(drive) >>> free = GetTotalDiskSpace(drive) >>> used = (total - free) >>> return used >>> >>> def GetStorage(self): >>> server = wmi.WMI(self.host) >>> print "Gather information on %s\n" % self.host >>> outfile.write("%s ::\n" % self.host) >>> for disk in server.Win32_LogicalDisk(): >>> if disk.DriveType == 3: >>> total = long(disk.Size) /1073741824.0 >>> free = long(disk.FreeSpace) /1073741824.0 >>> used = (total - free) >>> per_used = (used * 100) / total >>> outfile.write("\tDrive %s\n" % disk.Name) >>> outfile.write("\t\tTotal Size: %3.2f GB\n" % total) >>> outfile.write("\t\tFree Space: %3.2f GB\n" % free) >>> outfile.write("\t\tUsed Space: %3.2f GB\n" % used) >>> outfile.write('\t\tPercent Used: %.2f \n' % per_used) >>> >>> def GetNodeName(): >>> for os in server.Win32_OperatingSystem(): >>> activeNode = server.CSName >>> return activeNode >>> >>> if __name__ == '__main__': >>> >>> infile = open('san.txt', 'r') >>> outfile = open('test4.txt', 'w') >>> >>> for host in infile.readlines(): >>> host = host.strip() >>> try: >>> server = SysInfo(host) >>> server.GetStorage() >>> outfile.write("\n") >>> except KeyboardInterrupt: >>> print "The user canceled the job.\n" >>> sys.exit(0) >>> except: >>> outfile.write("%s does not appear to be available.\n\n" % host) >>> >>> print "Done!\n" >>> >>> infile.close() >>> outfile.close() >>> >>> -- >>> Thanks, >>> >>> Eric Lake >>> _______________________________________________ >>> CentralOH mailing list >>> CentralOH at python.org >>> http://mail.python.org/mailman/listinfo/centraloh >>> >>> >> >> >> >> -- >> Thanks, >> >> Eric Lake >> _______________________________________________ >> CentralOH mailing list >> CentralOH at python.org >> http://mail.python.org/mailman/listinfo/centraloh >> > -- Thanks, Eric Lake From ericlake at gmail.com Wed Jul 9 17:18:41 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 11:18:41 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> Message-ID: <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> Actually that did help and I saw another typo. I was getting 0.0 back but that is because I was using free = GetTotalDiskSpace(self.drive) when it should have been free = GetFreeDiskSpace(self.drive) On Wed, Jul 9, 2008 at 11:14 AM, Eric Lake wrote: > That seems to be the fix there. If I have something like the following: > > def GetTotalDiskSpace(self, drive): > self.drive = drive > for disk in self.server.Win32_LogicalDisk(): > if disk.Name == self.drive: > total = long(disk.Size) /1073741824.0 > return total > > def GetFreeDiskSpace(self, drive): > self.drive = drive > for disk in self.server.Win32_LogicalDisk(): > if disk.Name == self.drive: > free = long(disk.FreeSpace) /1073741824.0 > return free > > def GetUsedDiskSpace(self, drive): > self.drive = drive > total = GetTotalDiskSpace(self.drive) > free = GetTotalDiskSpace(self.drive) > used = (total - free) > return used > > should I change the: > > total = GetTotalDiskSpace(self.drive) > > to > > total = self.GetTotalDiskSpace(self.drive) > > On Wed, Jul 9, 2008 at 11:07 AM, Steven Huwig wrote: >> How about putting initialization code in the __init__ method instead? >> >> def __init__(self, hostname): >> self.host = hostname >> self.server = wmi.WMI(self.host) >> >> and replace all references to server with self.server . >> >> >> On Wed, Jul 9, 2008 at 10:55 AM, Eric Lake wrote: >>> The output above was from a run of the script with >>> GetLocalDrives(self) set. I had to change it to the following to make >>> it work: >>> >>> import sys >>> import wmi >>> >>> class SysInfo(object): >>> def __init__(self, hostname): >>> self.host = hostname >>> >>> def GetLocalDrives(self): >>> server = wmi.WMI(self.host) >>> driveList = [] >>> for disk in server.Win32_LogicalDisk(): >>> if disk.DriveType == 3: >>> driveList.append(str(disk.Name)) >>> return driveList >>> >>> I would like to not have to do 'server = wmi.WMI(self.host)' in every >>> method. Once I call mach = diskspace.SysInfo('localhost') I would like >>> the wmi stuff to be set. >>> >>> On Wed, Jul 9, 2008 at 10:26 AM, Sam Corder wrote: >>>> Change def GetLocalDrives() >>>> to >>>> def GetLocalDrives(self) >>>> and it will work. All methods attached to an instance of a class need to take self as the first parameter. >>>> >>>> ----- Original Message ----- >>>> From: Eric Lake >>>> To: centraloh at python.org >>>> Sent: Wednesday, July 9, 2008 10:23:19 AM GMT-0500 Auto-Detected >>>> Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) >>>> >>>> I am trying to write a script that I can use to gather information >>>> about the windows servers we have in our network. I started off with >>>> it being just a procedural script and I am now trying to put all of >>>> the functions in a class. This is still very much a work in progress. >>>> What can I do to improve on this / make it work? Any help would be >>>> appreciated. When I run the following from ipython to test it against >>>> my local machine I get this output: >>>> >>>> In [64]: server = diskspace.SysInfo('localhost') >>>> >>>> In [65]: server.GetLocalDrives() >>>> --------------------------------------------------------------------------- >>>> TypeError Traceback (most recent call last) >>>> >>>> C:\Documents and Settings\elake\Desktop\ in () >>>> >>>> TypeError: GetLocalDrives() takes no arguments (1 given) >>>> >>>> >>>> >>>> import sys >>>> import wmi >>>> >>>> class SysInfo(object): >>>> def __init__(self, hostname): >>>> self.host = hostname >>>> server = wmi.WMI(self.host) >>>> >>>> def GetLocalDrives(): >>>> driveList = [] >>>> for disk in self.Win32_LogicalDisk(): >>>> if disk.DriveType == 3: >>>> driveList.append(str(disk.Name)) >>>> return driveList >>>> >>>> def GetTotalDiskSize(drive): >>>> for disk in server.Win32_LogicalDisk(): >>>> if disk.Name == drive: >>>> total = long(disk.Size) /1073741824.0 >>>> return total >>>> >>>> def GetFreeDiskSpace(drive): >>>> for disk in server.Win32_LogicalDisk(): >>>> if disk.Name == drive: >>>> free = long(disk.FreeSpace) /1073741824.0 >>>> return free >>>> >>>> def GetUsedDiskSpace(drive): >>>> total = GetTotalDiskSpace(drive) >>>> free = GetTotalDiskSpace(drive) >>>> used = (total - free) >>>> return used >>>> >>>> def GetStorage(self): >>>> server = wmi.WMI(self.host) >>>> print "Gather information on %s\n" % self.host >>>> outfile.write("%s ::\n" % self.host) >>>> for disk in server.Win32_LogicalDisk(): >>>> if disk.DriveType == 3: >>>> total = long(disk.Size) /1073741824.0 >>>> free = long(disk.FreeSpace) /1073741824.0 >>>> used = (total - free) >>>> per_used = (used * 100) / total >>>> outfile.write("\tDrive %s\n" % disk.Name) >>>> outfile.write("\t\tTotal Size: %3.2f GB\n" % total) >>>> outfile.write("\t\tFree Space: %3.2f GB\n" % free) >>>> outfile.write("\t\tUsed Space: %3.2f GB\n" % used) >>>> outfile.write('\t\tPercent Used: %.2f \n' % per_used) >>>> >>>> def GetNodeName(): >>>> for os in server.Win32_OperatingSystem(): >>>> activeNode = server.CSName >>>> return activeNode >>>> >>>> if __name__ == '__main__': >>>> >>>> infile = open('san.txt', 'r') >>>> outfile = open('test4.txt', 'w') >>>> >>>> for host in infile.readlines(): >>>> host = host.strip() >>>> try: >>>> server = SysInfo(host) >>>> server.GetStorage() >>>> outfile.write("\n") >>>> except KeyboardInterrupt: >>>> print "The user canceled the job.\n" >>>> sys.exit(0) >>>> except: >>>> outfile.write("%s does not appear to be available.\n\n" % host) >>>> >>>> print "Done!\n" >>>> >>>> infile.close() >>>> outfile.close() >>>> >>>> -- >>>> Thanks, >>>> >>>> Eric Lake >>>> _______________________________________________ >>>> CentralOH mailing list >>>> CentralOH at python.org >>>> http://mail.python.org/mailman/listinfo/centraloh >>>> >>>> >>> >>> >>> >>> -- >>> Thanks, >>> >>> Eric Lake >>> _______________________________________________ >>> CentralOH mailing list >>> CentralOH at python.org >>> http://mail.python.org/mailman/listinfo/centraloh >>> >> > > > > -- > Thanks, > > Eric Lake > -- Thanks, Eric Lake From brian.costlow at gmail.com Wed Jul 9 18:06:29 2008 From: brian.costlow at gmail.com (Brian Costlow) Date: Wed, 9 Jul 2008 12:06:29 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> Message-ID: <89d8b1b00807090906v2bb1d4d1nd15b3a921f76e9fc@mail.gmail.com> Eric, A couple of other things I noticed. You use one of these two constructs in all the methods. for disk in server.Win32_LogicalDisk(): for disk in server.Win32_LogicalDisk(): if disk.DriveType == 3: Since it doesn't seem these would change for this script between the object creation and calling the methods, I'd refactor them into the init as well. class SysInfo(object): def __init__(self, hostname): self.host = hostname server = wmi.WMI(self.host) self.disks = [disk for disk in server.Win32_LogicalDisk()] self.localDisks [ disk for disk in self.disks if disk.DriveType == 3] Then you can iterate the lists in your methods. def GetStorage(self): for disk in self.localDisks: Also, it won't matter much in a one-pager, but if you were doing anything bigger, this might bite you. It looks like you're creating a global variable for the outfile, then referring to that implicitly from inside an object method. Typically, Id try to open/close that resource inside the method that uses it. If it had to come from outside, Id pass it explicitly just so the code was clearer. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ericlake at gmail.com Wed Jul 9 18:27:24 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 12:27:24 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <89d8b1b00807090906v2bb1d4d1nd15b3a921f76e9fc@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> <89d8b1b00807090906v2bb1d4d1nd15b3a921f76e9fc@mail.gmail.com> Message-ID: <15c903070807090927oa93acbekdb405cf2892e51bd@mail.gmail.com> Using: self.disks = [disk for disk in self.server.Win32_LogicalDisk()] self.localDisks = [ disk for disk in self.disks if disk.DriveType == 3] would then get the disk information every time I call the class though wouldn't it? What I am trying to write is a general purpose class that I can use to get all kinds of information from my servers. I have removed the input and output file stuff. here is the class as it stands currently: import string import wmi class SysInfo(object): def __init__(self, hostname): self.host = hostname self.server = wmi.WMI(self.host) def GetLocalDrives(self): driveList = [] for disk in self.server.Win32_LogicalDisk(): if disk.DriveType == 3: driveList.append(str(disk.Name)) return driveList def GetTotalDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: total = long(disk.Size) /1073741824.0 return total def GetFreeDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: free = long(disk.FreeSpace) /1073741824.0 return free def GetUsedDiskSpace(self, drive): self.drive = drive total = self.GetTotalDiskSpace(self.drive) free = self.GetFreeDiskSpace(self.drive) used = (total - free) return used def GetCpuList(self): cpulist = [] cpudict = {} for cpu in self.server.Win32_Processor(): name = string.strip(str(cpu.Name)) deviceid = str(cpu.DeviceID) cpudict = {deviceid:name} cpulist.append(cpudict) return cpulist def GetNumCpu(self): cpus = self.GetCpuList() return len(cpus) def GetNodeName(self): # This is for when you are looking at a clustered env and # want to know who the active node is. for os in self.server.Win32_OperatingSystem(): activeNode = os.CSName return str(activeNode) On Wed, Jul 9, 2008 at 12:06 PM, Brian Costlow wrote: > Eric, > > A couple of other things I noticed. > > You use one of these two constructs in all the methods. > > for disk in server.Win32_LogicalDisk(): > > for disk in server.Win32_LogicalDisk(): > if disk.DriveType == 3: > > Since it doesn't seem these would change for this script between the object > creation and calling the methods, I'd refactor them into the init as well. > > class SysInfo(object): > def __init__(self, hostname): > self.host = hostname > server = wmi.WMI(self.host) > self.disks = [disk for disk in server.Win32_LogicalDisk()] > self.localDisks [ disk for disk in self.disks if disk.DriveType == > 3] > > Then you can iterate the lists in your methods. > > def GetStorage(self): > for disk in self.localDisks: > > Also, it won't matter much in a one-pager, but if you were doing anything > bigger, this might bite you. It looks like you're creating a global variable > for the outfile, then referring to that implicitly from inside an object > method. Typically, Id try to open/close that resource inside the method that > uses it. If it had to come from outside, Id pass it explicitly just so the > code was clearer. > -- Thanks, Eric Lake From brian.costlow at gmail.com Wed Jul 9 19:56:56 2008 From: brian.costlow at gmail.com (Brian Costlow) Date: Wed, 9 Jul 2008 13:56:56 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <15c903070807090927oa93acbekdb405cf2892e51bd@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> <89d8b1b00807090906v2bb1d4d1nd15b3a921f76e9fc@mail.gmail.com> <15c903070807090927oa93acbekdb405cf2892e51bd@mail.gmail.com> Message-ID: <89d8b1b00807091056s2835ee23ya6bf57413708f9e2@mail.gmail.com> You have a point. In the original code, the class definition was inline with the script calling it, and every time you instantiated the object, you then called methods that called Win32_LogicalDisk. If you're going to use the class such that sometimes the calling code does foo = SysInfo(somehost) foo.GetCpuList() and never uses the disk info methods, then my suggestion is 'doing work' that you don't need to do. On the other hand, you still have code that repeats itself, that you should think about refactoring in some way. I didn't run this (my windows box isn't handy) but GetTotalDiskSpace and GetFreeDiskSpace look like they will die if you feed it a non-existing drive, since you will end up returning a name you haven't defined. On Wed, Jul 9, 2008 at 12:27 PM, Eric Lake wrote: > Using: > > self.disks = [disk for disk in self.server.Win32_LogicalDisk()] > self.localDisks = [ disk for disk in self.disks if disk.DriveType > == 3] > > would then get the disk information every time I call the class though > wouldn't it? What I am trying to write is a general purpose class that > I can use to get all kinds of information from my servers. I have > removed the input and output file stuff. here is the class as it > stands currently: > > import string > import wmi > > class SysInfo(object): > def __init__(self, hostname): > self.host = hostname > self.server = wmi.WMI(self.host) > > def GetLocalDrives(self): > driveList = [] > for disk in self.server.Win32_LogicalDisk(): > if disk.DriveType == 3: > driveList.append(str(disk.Name)) > return driveList > > def GetTotalDiskSpace(self, drive): > self.drive = drive > for disk in self.server.Win32_LogicalDisk(): > if disk.Name == self.drive: > total = long(disk.Size) /1073741824.0 > return total > > def GetFreeDiskSpace(self, drive): > self.drive = drive > for disk in self.server.Win32_LogicalDisk(): > if disk.Name == self.drive: > free = long(disk.FreeSpace) /1073741824.0 > return free > > def GetUsedDiskSpace(self, drive): > self.drive = drive > total = self.GetTotalDiskSpace(self.drive) > free = self.GetFreeDiskSpace(self.drive) > used = (total - free) > return used > > def GetCpuList(self): > cpulist = [] > cpudict = {} > for cpu in self.server.Win32_Processor(): > name = string.strip(str(cpu.Name)) > deviceid = str(cpu.DeviceID) > cpudict = {deviceid:name} > cpulist.append(cpudict) > return cpulist > > def GetNumCpu(self): > cpus = self.GetCpuList() > return len(cpus) > > def GetNodeName(self): > # This is for when you are looking at a clustered env and > # want to know who the active node is. > for os in self.server.Win32_OperatingSystem(): > activeNode = os.CSName > return str(activeNode) > > > On Wed, Jul 9, 2008 at 12:06 PM, Brian Costlow > wrote: > > Eric, > > > > A couple of other things I noticed. > > > > You use one of these two constructs in all the methods. > > > > for disk in server.Win32_LogicalDisk(): > > > > for disk in server.Win32_LogicalDisk(): > > if disk.DriveType == 3: > > > > Since it doesn't seem these would change for this script between the > object > > creation and calling the methods, I'd refactor them into the init as > well. > > > > class SysInfo(object): > > def __init__(self, hostname): > > self.host = hostname > > server = wmi.WMI(self.host) > > self.disks = [disk for disk in server.Win32_LogicalDisk()] > > self.localDisks [ disk for disk in self.disks if disk.DriveType > == > > 3] > > > > Then you can iterate the lists in your methods. > > > > def GetStorage(self): > > for disk in self.localDisks: > > > > Also, it won't matter much in a one-pager, but if you were doing anything > > bigger, this might bite you. It looks like you're creating a global > variable > > for the outfile, then referring to that implicitly from inside an object > > method. Typically, Id try to open/close that resource inside the method > that > > uses it. If it had to come from outside, Id pass it explicitly just so > the > > code was clearer. > > > > > > -- > Thanks, > > Eric Lake > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ericlake at gmail.com Wed Jul 9 20:04:22 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 9 Jul 2008 14:04:22 -0400 Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <89d8b1b00807091056s2835ee23ya6bf57413708f9e2@mail.gmail.com> References: <15c903070807090723o13e25e75h173b491b36073508@mail.gmail.com> <12344042.171215613590105.JavaMail.root@spring.codeargyle.com> <15c903070807090755r7bfeefc5wf1aa0a3c328596c2@mail.gmail.com> <7505f2a60807090807h6bddef65q24de0a75fcdff5f3@mail.gmail.com> <15c903070807090814o33982973ga91fe348fafbba88@mail.gmail.com> <15c903070807090818m44411529t89faf4f5aef25625@mail.gmail.com> <89d8b1b00807090906v2bb1d4d1nd15b3a921f76e9fc@mail.gmail.com> <15c903070807090927oa93acbekdb405cf2892e51bd@mail.gmail.com> <89d8b1b00807091056s2835ee23ya6bf57413708f9e2@mail.gmail.com> Message-ID: <15c903070807091104u342359f5raab015d021d03568@mail.gmail.com> Good point. I think that doing the following would catch that. I'm still very new to the OOP stuff so I'm not sure how to go about refactoring it. def GetTotalDiskSpace(self, drive): self.drive = drive try: for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: total = long(disk.Size) /1073741824.0 return total except UnboundLocalError: return 'Drive Not Found' def GetFreeDiskSpace(self, drive): self.drive = drive try: for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: free = long(disk.FreeSpace) /1073741824.0 return total except UnboundLocalError: return 'Drive Not Found' On Wed, Jul 9, 2008 at 1:56 PM, Brian Costlow wrote: > You have a point. > > In the original code, the class definition was inline with the script > calling it, and every time you instantiated the object, you then called > methods that > called Win32_LogicalDisk. > > If you're going to use the class such that sometimes the calling code does > > foo = SysInfo(somehost) > foo.GetCpuList() > > and never uses the disk info methods, then my suggestion is 'doing work' > that you don't need to do. > > On the other hand, you still have code that repeats itself, that you should > think about refactoring in some way. > > I didn't run this (my windows box isn't handy) but GetTotalDiskSpace and > GetFreeDiskSpace look like they will die if you feed it a non-existing > drive, since you will end up returning a name you haven't defined. > > > -- Thanks, Eric Lake From samus at codeargyle.com Wed Jul 9 20:17:29 2008 From: samus at codeargyle.com (Sam Corder) Date: Wed, 9 Jul 2008 14:17:29 -0400 (EDT) Subject: [CentralOH] Help with learning how to use a class (please don't laugh :) ) In-Reply-To: <15c903070807091104u342359f5raab015d021d03568@mail.gmail.com> Message-ID: <714001.261215627449763.JavaMail.root@spring.codeargyle.com> I'd suggest not having two different return types coming back from a method. You could either raise an exception for an invalid drive or return a value like -1. My personal preference is for exceptions but there are varying schools of thoughts when you should return error codes and when you should raise exceptions. def GetTotalDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == drive: return = long(disk.Size) /1073741824.0 return -1 Or with exceptions: def GetTotalDiskSpace(self, drive): self.drive = drive for disk in self.server.Win32_LogicalDisk(): if disk.Name == drive: return = long(disk.Size) /1073741824.0 raise ValueError('Invalid Drive') A couple other pointers. You don't even need a total variable here since your if statement will only execute once. You don't need to store drive in an instance variable unless you are going to use it in another method that doesn't receive the drive parameter. In that case you could end up with some weird behavior if you don't call the different methods in exactly the right order. -Sam ----- Original Message ----- From: Eric Lake To: Brian Costlow Cc: centraloh at python.org Sent: Wednesday, July 9, 2008 2:04:22 PM GMT-0500 Auto-Detected Subject: Re: [CentralOH] Help with learning how to use a class (please don't laugh :) ) Good point. I think that doing the following would catch that. I'm still very new to the OOP stuff so I'm not sure how to go about refactoring it. def GetTotalDiskSpace(self, drive): self.drive = drive try: for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: total = long(disk.Size) /1073741824.0 return total except UnboundLocalError: return 'Drive Not Found' def GetFreeDiskSpace(self, drive): self.drive = drive try: for disk in self.server.Win32_LogicalDisk(): if disk.Name == self.drive: free = long(disk.FreeSpace) /1073741824.0 return total except UnboundLocalError: return 'Drive Not Found' On Wed, Jul 9, 2008 at 1:56 PM, Brian Costlow wrote: > You have a point. > > In the original code, the class definition was inline with the script > calling it, and every time you instantiated the object, you then called > methods that > called Win32_LogicalDisk. > > If you're going to use the class such that sometimes the calling code does > > foo = SysInfo(somehost) > foo.GetCpuList() > > and never uses the disk info methods, then my suggestion is 'doing work' > that you don't need to do. > > On the other hand, you still have code that repeats itself, that you should > think about refactoring in some way. > > I didn't run this (my windows box isn't handy) but GetTotalDiskSpace and > GetFreeDiskSpace look like they will die if you feed it a non-existing > drive, since you will end up returning a name you haven't defined. > > > -- Thanks, Eric Lake _______________________________________________ CentralOH mailing list CentralOH at python.org http://mail.python.org/mailman/listinfo/centraloh From cbc at unc.edu Mon Jul 14 17:46:59 2008 From: cbc at unc.edu (Chris Calloway) Date: Mon, 14 Jul 2008 11:46:59 -0400 Subject: [CentralOH] BootCampArama Final Reminder Message-ID: <100E9F29-33FE-44AB-AA2C-A851FC6320A4@unc.edu> Final reminder, we're in the last two weeks of open registration for PyCamp, Plone Boot Camp, and Advanced Plone Boot Camp: http://trizpug.org/boot-camp/2008/ Registration is now open for: PyCamp: Python Boot Camp, August 4 - 8 Plone Boot Camp: Customizing Plone, July 28 - August 1 Advanced Plone Boot Camp: Plone 3 Techniques, August 4 - 7 All of these take place on the campus of the University of North Carolina at Chapel Hill in state of the art high tech classrooms, with free mass transit, low-cost accommodations with free wireless, and convenient dining options. Plone Boot Camp is taught by Joel Burton, twice chair of the Plone Foundation. Joel has logged more the 200 days at the head of Plone classrooms on four continents. See plonebootcamps.com for dozens of testimonials from Joel's students. PyCamp is taught by Chris Calloway, facilitator for TriZPUG and application analyst for the Southeast Coastal Ocean Observing System. Chris has developed PyCamp for over 1500 hours on behalf of Python user groups. Early bird registration runs through June 30. So register today! PyCamp is TriZPUG's Python Boot Camp, which takes a programmer familiar with basic programming concepts to the status of Python developer with one week of training. If you have previous scripting or programming experience and want to step into Python programming as quickly and painlessly as possible, this boot camp is for you. PyCamp is also the perfect follow-on to Plone Boot Camp: Customizing Plone the previous week. At Plone Boot Camp: Customizing Plone you will learn the essentials you need to build your Plone site and deploy it. This course is the most popular in the Plone world--for a good reason: it teaches you practical skills in a friendly, hands-on format. This bootcamp is aimed at: * people with HTML or web design experience * people with some or no Python experience * people with some or no Zope/Plone experience It covers using Plone, customizing, and deploying Plone sites. At Advanced Plone Boot Camp: Plone 3 Techniques you will learn to build a site using the best practices of Plone 3 as well as advance your skills in scripting and developing for Plone. The course covers the new technologies in Plone 3.0 and 3.1intended for site integrators and developers: our new portlet infrastructure, viewlets, versioning, and a friendly introduction to Zope 3 component architecture. Now, updated for Plone 3.1! The course is intended for people who have experience with the basics of Plone site development and HTML/CSS. It will cover what you need to know to take advantage of these new technologies in Plone 3. For more information contact: info at trizpug.org -- Sincerely, Chris Calloway http://www.secoora.org office: 332 Chapman Hall phone: (919) 599-3530 mail: Campus Box #3300, UNC-CH, Chapel Hill, NC 27599 From mark at microenh.com Tue Jul 22 23:37:53 2008 From: mark at microenh.com (Mark Erbaugh) Date: Tue, 22 Jul 2008 17:37:53 -0400 Subject: [CentralOH] Generator and DRY Message-ID: <1216762674.23770.15.camel@notebook> Here are part of method I wrote that provides a generator: def read(self, id, size=None): i = gen_data.next() try: while True: while len(buffer) >= read_size: yield(''.join(buffer[:read_size])) del buffer[:read_size] i = gen_data.next() except StopIteration: pass while len(buffer) >= read_size: yield(''.join(buffer[:read_size])) del buffer[:read_size] if len(buffer): yield(''.join(buffer)) The purpose of this code is to take data from another generator (gen_data) and deliver it in chunks of the specified size (except the last). Code not shown handles possible decompression (zlib) of the data. The interesting thing is that there is some duplicate code: while len(buffer) >= read_size: yield(''.join(buffer[:read_size])) del buffer[:read_size] I couldn't come up with any way to rewrite the loop to eliminate the duplicate sections. Actually, I could by buffering the data, but I don't want to do that. The chunks could be quite large. If this were "normal" code, I could write an embedded function and just call function that in both places. However, since the embedded function contains a yield() call, it now becomes a generator itself and the re-factored code doesn't do work properly. Is there a way to create an embedded function where the yield() call is still tied to the parent function/method? Thanks, Mark From jeff at taupro.com Wed Jul 23 02:26:26 2008 From: jeff at taupro.com (Jeff Rush) Date: Tue, 22 Jul 2008 19:26:26 -0500 Subject: [CentralOH] Generator and DRY In-Reply-To: <1216762674.23770.15.camel@notebook> References: <1216762674.23770.15.camel@notebook> Message-ID: <48867AB2.8050307@taupro.com> Mark Erbaugh wrote: > Here are part of method I wrote that provides a generator: > > def read(self, id, size=None): > i = gen_data.next() > try: > while True: > while len(buffer) >= read_size: > yield(''.join(buffer[:read_size])) > del buffer[:read_size] > i = gen_data.next() > except StopIteration: > pass > while len(buffer) >= read_size: > yield(''.join(buffer[:read_size])) > del buffer[:read_size] > if len(buffer): > yield(''.join(buffer)) > > > The purpose of this code is to take data from another generator > (gen_data) and deliver it in chunks of the specified size (except the > last). Code not shown handles possible decompression (zlib) of the > data. > > However, since the embedded function contains a yield() call, it now > becomes a generator itself and the re-factored code doesn't do work > properly. > > Is there a way to create an embedded function where the yield() call is > still tied to the parent function/method? I don't have a quick answer to your interesting problem of controlling the "yield" space of nested functions (I'll research it) but in case it is useful in some obsure way, here is a simple expression for chunking any generator: for chunk in iter(lambda: f.read(block_size), ''): ... It doesn't handle your decompression or careful use of memory for huge chunks, but perhaps refactoring your code say around gen_data.next() into something more like gen_data.read(chunk_size) and layering this with iter() might shed light on another approach. Just a passing thought... I think iter() is cool. -Jeff From steven_h at acm.org Wed Jul 23 03:55:35 2008 From: steven_h at acm.org (Steven Huwig) Date: Tue, 22 Jul 2008 21:55:35 -0400 Subject: [CentralOH] Generator and DRY In-Reply-To: <1216762674.23770.15.camel@notebook> References: <1216762674.23770.15.camel@notebook> Message-ID: <7505f2a60807221855j199af95ev14989280fadf637b@mail.gmail.com> I would solve the chunking a different way, but maybe it's too clever by half for your code. It also has a little repetition. :-) import itertools def chunker(size, stream): chunk = list(itertools.islice(stream, size)) while chunk: yield ''.join(chunk) chunk = list(itertools.islice(stream, size)) >>> stream = (c for c in "abcdefghijklmnopqrstuvwxyz") >>> size = 5 >>> x = chunker(size, stream) >>> x >>> list(x) ['abcde', 'fghij', 'klmno', 'pqrst', 'uvwxy', 'z'] >>> -- Steve On Tue, Jul 22, 2008 at 5:37 PM, Mark Erbaugh wrote: > Here are part of method I wrote that provides a generator: > > def read(self, id, size=None): > i = gen_data.next() > try: > while True: > while len(buffer) >= read_size: > yield(''.join(buffer[:read_size])) > del buffer[:read_size] > i = gen_data.next() > except StopIteration: > pass > while len(buffer) >= read_size: > yield(''.join(buffer[:read_size])) > del buffer[:read_size] > if len(buffer): > yield(''.join(buffer)) > > > The purpose of this code is to take data from another generator > (gen_data) and deliver it in chunks of the specified size (except the > last). Code not shown handles possible decompression (zlib) of the > data. > > The interesting thing is that there is some duplicate code: > > while len(buffer) >= read_size: > yield(''.join(buffer[:read_size])) > del buffer[:read_size] > > I couldn't come up with any way to rewrite the loop to eliminate the > duplicate sections. Actually, I could by buffering the data, but I don't > want to do that. The chunks could be quite large. > > If this were "normal" code, I could write an embedded function and just > call function that in both places. > > However, since the embedded function contains a yield() call, it now > becomes a generator itself and the re-factored code doesn't do work > properly. > > Is there a way to create an embedded function where the yield() call is > still tied to the parent function/method? > > Thanks, > Mark > > > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > http://mail.python.org/mailman/listinfo/centraloh > From ericlake at gmail.com Wed Jul 23 13:52:49 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 23 Jul 2008 07:52:49 -0400 Subject: [CentralOH] parsing Windows command line output Message-ID: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> I have been looking for a way to monitor a Windows cluster that we have at work. I was really hoping for a good wmi class that I could use from my XP machine to do it but I have not been lucky finding one. I did however come across the 'cluster' command. I am thinking that I could just call that from within my python code and parse the output to get what I need. I want to get all of the data from the output and then put it in a database. I can not see how to split the lines up though. It would be easy if it was comma delimited but it seems to use a varying number of spaces. My only thought is that I could do a split on anything that is more than 2 spaces. The output of the command is in the attached file. -- Thanks, Eric Lake -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: qry1.txt URL: From ericlake at gmail.com Wed Jul 23 14:44:27 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 23 Jul 2008 08:44:27 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> Message-ID: <15c903070807230544o6e309003o97b373afe46355b1@mail.gmail.com> I may have answered my own question. I know that this could probably be done in a more elegant way so I am looking for suggestions. Here is the code that I have come up with so far: data = open('file.txt', 'r') data.next() data.next() data.next() data.next() for line in data: clusdata = [] line.strip() info = line.split(' ') for x in info: if x != '': x = x.strip() if x .endswith('\\r\\n'): x = x.strip('\\r\\n') clusdata.append(x) print clusdata data.close() On Wed, Jul 23, 2008 at 7:52 AM, Eric Lake wrote: > I have been looking for a way to monitor a Windows cluster that we > have at work. I was really hoping for a good wmi class that I could > use from my XP machine to do it but I have not been lucky finding one. > I did however come across the 'cluster' command. I am thinking that I > could just call that from within my python code and parse the output > to get what I need. I want to get all of the data from the output and > then put it in a database. I can not see how to split the lines up > though. It would be easy if it was comma delimited but it seems to use > a varying number of spaces. My only thought is that I could do a split > on anything that is more than 2 spaces. > > The output of the command is in the attached file. > > -- > Thanks, > > Eric Lake > -- Thanks, Eric Lake From ericlake at gmail.com Wed Jul 23 15:25:22 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 23 Jul 2008 09:25:22 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <15c903070807230544o6e309003o97b373afe46355b1@mail.gmail.com> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> <15c903070807230544o6e309003o97b373afe46355b1@mail.gmail.com> Message-ID: <15c903070807230625w3de0e9b6i3d09a5c04f01bce7@mail.gmail.com> Turns out this may not work because Microsoft does not always separate the columns of data with 2 or more spaces. So it looks like I'm still stumped on this one. On Wed, Jul 23, 2008 at 8:44 AM, Eric Lake wrote: > I may have answered my own question. I know that this could probably > be done in a more elegant way so I am looking for suggestions. Here is > the code that I have come up with so far: > > data = open('file.txt', 'r') > > data.next() > data.next() > data.next() > data.next() > > for line in data: > clusdata = [] > line.strip() > info = line.split(' ') > for x in info: > if x != '': > x = x.strip() > if x .endswith('\\r\\n'): > x = x.strip('\\r\\n') > clusdata.append(x) > print clusdata > > data.close() > > > > On Wed, Jul 23, 2008 at 7:52 AM, Eric Lake wrote: >> I have been looking for a way to monitor a Windows cluster that we >> have at work. I was really hoping for a good wmi class that I could >> use from my XP machine to do it but I have not been lucky finding one. >> I did however come across the 'cluster' command. I am thinking that I >> could just call that from within my python code and parse the output >> to get what I need. I want to get all of the data from the output and >> then put it in a database. I can not see how to split the lines up >> though. It would be easy if it was comma delimited but it seems to use >> a varying number of spaces. My only thought is that I could do a split >> on anything that is more than 2 spaces. >> >> The output of the command is in the attached file. >> >> -- >> Thanks, >> >> Eric Lake >> > > > > -- > Thanks, > > Eric Lake > -- Thanks, Eric Lake From mpeters42 at gmail.com Wed Jul 23 15:30:27 2008 From: mpeters42 at gmail.com (Mark Peters) Date: Wed, 23 Jul 2008 09:30:27 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <15c903070807230625w3de0e9b6i3d09a5c04f01bce7@mail.gmail.com> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> <15c903070807230544o6e309003o97b373afe46355b1@mail.gmail.com> <15c903070807230625w3de0e9b6i3d09a5c04f01bce7@mail.gmail.com> Message-ID: <25a37b830807230630q5d42135qa66af17c558705db@mail.gmail.com> Use the default option to split: *split*( [sep [,maxsplit]]) Return a list of the words in the string, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done. (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified, then there is no limit on the number of splits (all possible splits are made). Consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, " '1?2'.split(',')"returns "['1', '', '2']"). The sep argument may consist of multiple characters (for example, "'1, 2, 3'.split(', ')" returns "['1', '2', '3']"). Splitting an empty string with a specified separator returns " ['']". If sep is not specified or is None, a different splitting algorithm is applied. First, whitespace characters (spaces, tabs, newlines, returns, and formfeeds) are stripped from both ends. Then, words are separated by arbitrary length strings of whitespace characters. Consecutive whitespace delimiters are treated as a single delimiter ("'1 2 3'.split()" returns "['1', '2', '3']"). Splitting an empty string or a string consisting of just whitespace returns an empty list. By default, it splits using *any consecutive* whitespace. Alternatively, you could use a regex. Mark Peters On Wed, Jul 23, 2008 at 9:25 AM, Eric Lake wrote: > Turns out this may not work because Microsoft does not always separate > the columns of data with 2 or more spaces. So it looks like I'm still > stumped on this one. > > On Wed, Jul 23, 2008 at 8:44 AM, Eric Lake wrote: > > I may have answered my own question. I know that this could probably > > be done in a more elegant way so I am looking for suggestions. Here is > > the code that I have come up with so far: > > > > data = open('file.txt', 'r') > > > > data.next() > > data.next() > > data.next() > > data.next() > > > > for line in data: > > clusdata = [] > > line.strip() > > info = line.split(' ') > > for x in info: > > if x != '': > > x = x.strip() > > if x .endswith('\\r\\n'): > > x = x.strip('\\r\\n') > > clusdata.append(x) > > print clusdata > > > > data.close() > > > > > > > > On Wed, Jul 23, 2008 at 7:52 AM, Eric Lake wrote: > >> I have been looking for a way to monitor a Windows cluster that we > >> have at work. I was really hoping for a good wmi class that I could > >> use from my XP machine to do it but I have not been lucky finding one. > >> I did however come across the 'cluster' command. I am thinking that I > >> could just call that from within my python code and parse the output > >> to get what I need. I want to get all of the data from the output and > >> then put it in a database. I can not see how to split the lines up > >> though. It would be easy if it was comma delimited but it seems to use > >> a varying number of spaces. My only thought is that I could do a split > >> on anything that is more than 2 spaces. > >> > >> The output of the command is in the attached file. > >> > >> -- > >> Thanks, > >> > >> Eric Lake > >> > > > > > > > > -- > > Thanks, > > > > Eric Lake > > > > > > -- > Thanks, > > Eric Lake > _______________________________________________ > CentralOH mailing list > CentralOH at python.org > http://mail.python.org/mailman/listinfo/centraloh > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ericlake at gmail.com Wed Jul 23 17:40:26 2008 From: ericlake at gmail.com (Eric Lake) Date: Wed, 23 Jul 2008 11:40:26 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <20080723112727.a22e3408.nludban@osc.edu> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> <20080723112727.a22e3408.nludban@osc.edu> Message-ID: <15c903070807230840i473d16cn299be3d9d828fb95@mail.gmail.com> Neil, That seems to do exactly what I need it to do. Now I just need to get to a point where I can understand what the heck it is doing :) On Wed, Jul 23, 2008 at 11:27 AM, Neil Ludban wrote: > On Wed, 23 Jul 2008 07:52:49 -0400 > "Eric Lake" wrote: >> I have been looking for a way to monitor a Windows cluster that we >> have at work. I was really hoping for a good wmi class that I could >> use from my XP machine to do it but I have not been lucky finding one. >> I did however come across the 'cluster' command. I am thinking that I >> could just call that from within my python code and parse the output >> to get what I need. I want to get all of the data from the output and >> then put it in a database. I can not see how to split the lines up >> though. It would be easy if it was comma delimited but it seems to use >> a varying number of spaces. My only thought is that I could do a split >> on anything that is more than 2 spaces. > > #!/usr/local/bin/python > > import re > > fin = open('cluster.txt', 'r') > > fin.readline() # Listing status for all available resources: > fin.readline() # > fin.readline() # Resource Group Node Status > nom_len = [ len(x) # - - - - > for x in re.findall('-+', fin.readline().strip()) ] > #print nom_len # [20, 20, 15, 6] > > def combinations(items, n): > if len(items) < n: > return > if n == 1: > for i in items: > yield [ i ] > return > for i in range(len(items)): > for rest in combinations(items[i+1:], n-1): > yield [ items[i] ] + rest > return > > #for c in combinations([ 'a', 'b', 'c', 'd' ], 2): > # print c > > def score(cols): > s = 100.0 > # small penalty if too long > s -= 0.20 * sum([ max(len(c) - n, 0.0) > for c, n in zip(cols, nom_len) ]) > # large penalty if too short > s -= 0.80 * sum([ max(n - len(c), 0.0) > for c, n in zip(cols, nom_len) ]) > # bonus for trailing whitespace? > return s > > for line in fin.readlines(): > line = line.strip() > cols = re.findall('\s+|[^\s]+', line) > #print cols > seps = range(1, len(cols), 2) > #print [ cols[i] for i in seps ] > best_cols = None > best_score = None > for seps in combinations(seps, 3): > tmp = [ ] > a = 0 > for b in seps: > tmp.append(''.join(cols[a:b+1])) > a = b + 1 > tmp.append(''.join(cols[a:])) > #print tmp > s = score(tmp) > if ((best_cols is None) or (s > best_score)): > best_cols = tmp > best_score = s > print [ c.strip() for c in best_cols ] > > #--# > -- Thanks, Eric Lake From wam at cisco.com Wed Jul 23 17:47:49 2008 From: wam at cisco.com (William McVey) Date: Wed, 23 Jul 2008 11:47:49 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <25a37b830807230630q5d42135qa66af17c558705db@mail.gmail.com> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> <15c903070807230544o6e309003o97b373afe46355b1@mail.gmail.com> <15c903070807230625w3de0e9b6i3d09a5c04f01bce7@mail.gmail.com> <25a37b830807230630q5d42135qa66af17c558705db@mail.gmail.com> Message-ID: <1216828069.6385.52.camel@tardis> On Wed, 2008-07-23 at 09:30 -0400, Mark Peters wrote: > Use the default option to split: The problem is that some of his fields (e.g. first and second) have embedded whitespace in the actual field values. If his second column didn't fluctuate between spaces and non-spaces, he would have been able to do something like: >>> line= "Quest SQL Watch Agent ORIONMFG1 APPS MFGSQL-S1A Online" >>> line.rsplit(None, 4) ['Quest SQL Watch Agent', 'ORIONMFG1', 'APPS', 'MFGSQL-S1A', 'Online'] However, that breaks on lines like: >>> line= "Cluster IP Address ORIONMFG-SAN1 MFGSQL-S1A Online" >>> line.rsplit(None, 4) ['Cluster IP', 'Address', 'ORIONMFG-SAN1', 'MFGSQL-S1A', 'Online'] Perhaps ORIONMFG-SAN1 is a special case and could be mapped to "ORIONMFG SAN1": >>> line.replace("ORIONMFG-SAN1", "ORIONMFG SAN1").rsplit(None, 4) ['Cluster IP Address', 'ORIONMFG', 'SAN1', 'MFGSQL-S1A', 'Online'] Ordinarily, parsing columnar output screams for string slices; however your format is particularly nasty in that the columns are *mostly* fixed width, but will (on a case by case basis) overflow the fixed width when a field is too long and turn into a delimited output format with an ambiguous field delimiter. A good example of this is that line that starts with "Quest SQL Watch Agent". If it weren't for the possibility of field overflow, you could do something like: for line in file("qry1.txt").readlines(): fields = line[:21], line[21:42], line[42:58], line[58:] resource, group, node, status = [x.strip() for x in fields] As it happens, this routine *will* parse the output you provided, but be aware that any resources that are longer than 21 characters will likely cause the routine to choke. Unless I knew that there was no possibility of field overflow, I'd try to stick to the rsplit() option, even if it requires a hack to map particular values into a more accommodating format. -- William P.S. I'd be really surprised if there is something that the cluster command is doing that couldn't be done directly within python using the pywin32 api. From nludban at osc.edu Wed Jul 23 17:27:27 2008 From: nludban at osc.edu (Neil Ludban) Date: Wed, 23 Jul 2008 11:27:27 -0400 Subject: [CentralOH] parsing Windows command line output In-Reply-To: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> References: <15c903070807230452p505fcc42g52e3a1def3ac206c@mail.gmail.com> Message-ID: <20080723112727.a22e3408.nludban@osc.edu> On Wed, 23 Jul 2008 07:52:49 -0400 "Eric Lake" wrote: > I have been looking for a way to monitor a Windows cluster that we > have at work. I was really hoping for a good wmi class that I could > use from my XP machine to do it but I have not been lucky finding one. > I did however come across the 'cluster' command. I am thinking that I > could just call that from within my python code and parse the output > to get what I need. I want to get all of the data from the output and > then put it in a database. I can not see how to split the lines up > though. It would be easy if it was comma delimited but it seems to use > a varying number of spaces. My only thought is that I could do a split > on anything that is more than 2 spaces. #!/usr/local/bin/python import re fin = open('cluster.txt', 'r') fin.readline() # Listing status for all available resources: fin.readline() # fin.readline() # Resource Group Node Status nom_len = [ len(x) # - - - - for x in re.findall('-+', fin.readline().strip()) ] #print nom_len # [20, 20, 15, 6] def combinations(items, n): if len(items) < n: return if n == 1: for i in items: yield [ i ] return for i in range(len(items)): for rest in combinations(items[i+1:], n-1): yield [ items[i] ] + rest return #for c in combinations([ 'a', 'b', 'c', 'd' ], 2): # print c def score(cols): s = 100.0 # small penalty if too long s -= 0.20 * sum([ max(len(c) - n, 0.0) for c, n in zip(cols, nom_len) ]) # large penalty if too short s -= 0.80 * sum([ max(n - len(c), 0.0) for c, n in zip(cols, nom_len) ]) # bonus for trailing whitespace? return s for line in fin.readlines(): line = line.strip() cols = re.findall('\s+|[^\s]+', line) #print cols seps = range(1, len(cols), 2) #print [ cols[i] for i in seps ] best_cols = None best_score = None for seps in combinations(seps, 3): tmp = [ ] a = 0 for b in seps: tmp.append(''.join(cols[a:b+1])) a = b + 1 tmp.append(''.join(cols[a:])) #print tmp s = score(tmp) if ((best_cols is None) or (s > best_score)): best_cols = tmp best_score = s print [ c.strip() for c in best_cols ] #--#