0001 """Utilities for the win32 Performance Data Helper module 0002 0003 Example: 0004 To get a single bit of data: 0005 >>> import win32pdhutil 0006 >>> win32pdhutil.GetPerformanceAttributes("Memory", "Available Bytes") 0007 6053888 0008 >>> win32pdhutil.FindPerformanceAttributesByName("python", counter="Virtual Bytes") 0009 [22278144] 0010 0011 First example returns data which is not associated with any specific instance. 0012 0013 The second example reads data for a specific instance - hence the list return - 0014 it would return one result for each instance of Python running. 0015 0016 In general, it can be tricky finding exactly the "name" of the data you wish to query. 0017 Although you can use <om win32pdh.EnumObjectItems>(None,None,(eg)"Memory", -1) to do this, 0018 the easiest way is often to simply use PerfMon to find out the names. 0019 """ 0020 0021 import win32pdh, string, time 0022 0023 error = win32pdh.error 0024 0025 # Handle some localization issues. 0026 # see http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q287/1/59.asp&NoWebContent=1 0027 # Build a map of english_counter_name: counter_id 0028 counter_english_map = {} 0029 0030 def find_pdh_counter_localized_name(english_name, machine_name = None): 0031 if not counter_english_map: 0032 import win32api, win32con 0033 counter_reg_value = win32api.RegQueryValueEx(win32con.HKEY_PERFORMANCE_DATA, "Counter 009") 0034 counter_list = counter_reg_value[0] 0035 for i in range(0, len(counter_list) - 1, 2): 0036 try: 0037 counter_id = int(counter_list[i]) 0038 except ValueError: 0039 continue 0040 counter_english_map[counter_list[i+1].lower()] = counter_id 0041 return win32pdh.LookupPerfNameByIndex(machine_name, counter_english_map[english_name.lower()]) 0042 0043 def GetPerformanceAttributes(object, counter, instance = None, inum=-1, format = win32pdh.PDH_FMT_LONG, machine=None): 0044 # NOTE: Many counters require 2 samples to give accurate results, 0045 # including "% Processor Time" (as by definition, at any instant, a 0046 # thread's CPU usage is either 0 or 100). To read counters like this, 0047 # you should copy this function, but keep the counter open, and call 0048 # CollectQueryData() each time you need to know. 0049 # See http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp 0050 # My older explanation for this was that the "AddCounter" process forced 0051 # the CPU to 100%, but the above makes more sense :) 0052 path = win32pdh.MakeCounterPath( (machine,object,instance, None, inum,counter) ) 0053 hq = win32pdh.OpenQuery() 0054 try: 0055 hc = win32pdh.AddCounter(hq, path) 0056 try: 0057 win32pdh.CollectQueryData(hq) 0058 type, val = win32pdh.GetFormattedCounterValue(hc, format) 0059 return val 0060 finally: 0061 win32pdh.RemoveCounter(hc) 0062 finally: 0063 win32pdh.CloseQuery(hq) 0064 0065 def FindPerformanceAttributesByName(instanceName, object = None, counter = None, format = win32pdh.PDH_FMT_LONG, machine = None, bRefresh=0): 0066 """Find peformance attributes by (case insensitive) instance name. 0067 0068 Given a process name, return a list with the requested attributes. 0069 Most useful for returning a tuple of PIDs given a process name. 0070 """ 0071 if object is None: object = find_pdh_counter_localized_name("Process", machine) 0072 if counter is None: counter = find_pdh_counter_localized_name("ID Process", machine) 0073 if bRefresh: # PDH docs say this is how you do a refresh. 0074 win32pdh.EnumObjects(None, machine, 0, 1) 0075 instanceName = string.lower(instanceName) 0076 items, instances = win32pdh.EnumObjectItems(None,None,object, -1) 0077 # Track multiple instances. 0078 instance_dict = {} 0079 for instance in instances: 0080 try: 0081 instance_dict[instance] = instance_dict[instance] + 1 0082 except KeyError: 0083 instance_dict[instance] = 0 0084 0085 ret = [] 0086 for instance, max_instances in instance_dict.items(): 0087 for inum in xrange(max_instances+1): 0088 if string.lower(instance) == instanceName: 0089 ret.append(GetPerformanceAttributes(object, counter, instance, inum, format, machine)) 0090 return ret 0091 0092 def ShowAllProcesses(): 0093 object = "Process" 0094 items, instances = win32pdh.EnumObjectItems(None,None,object, win32pdh.PERF_DETAIL_WIZARD) 0095 # Need to track multiple instances of the same name. 0096 instance_dict = {} 0097 for instance in instances: 0098 try: 0099 instance_dict[instance] = instance_dict[instance] + 1 0100 except KeyError: 0101 instance_dict[instance] = 0 0102 0103 # Bit of a hack to get useful info. 0104 items = ["ID Process"] + items[:5] 0105 print "Process Name", string.join(items,",") 0106 for instance, max_instances in instance_dict.items(): 0107 for inum in xrange(max_instances+1): 0108 hq = win32pdh.OpenQuery() 0109 hcs = [] 0110 for item in items: 0111 path = win32pdh.MakeCounterPath( (None,object,instance, None, inum, item) ) 0112 hcs.append(win32pdh.AddCounter(hq, path)) 0113 win32pdh.CollectQueryData(hq) 0114 # as per http://support.microsoft.com/default.aspx?scid=kb;EN-US;q262938, some "%" based 0115 # counters need two collections 0116 time.sleep(0.01) 0117 win32pdh.CollectQueryData(hq) 0118 print "%-15s\t" % (instance[:15]), 0119 for hc in hcs: 0120 type, val = win32pdh.GetFormattedCounterValue(hc, win32pdh.PDH_FMT_LONG) 0121 print "%5d" % (val), 0122 win32pdh.RemoveCounter(hc) 0123 print 0124 win32pdh.CloseQuery(hq) 0125 0126 def BrowseCallBackDemo(counter): 0127 machine, object, instance, parentInstance, index, counterName = \ 0128 win32pdh.ParseCounterPath(counter) 0129 0130 result = GetPerformanceAttributes(object, counterName, instance, index, win32pdh.PDH_FMT_DOUBLE, machine) 0131 print "Value of '%s' is" % counter, result 0132 print "Added '%s' on object '%s' (machine %s), instance %s(%d)-parent of %s" % (counterName, object, machine, instance, index, parentInstance) 0133 0134 def browse( callback = BrowseCallBackDemo, title="Python Browser", level=win32pdh.PERF_DETAIL_WIZARD): 0135 print "Virtual Bytes = ", FindPerformanceAttributesByName("python", counter="Virtual Bytes") 0136 print "Available Bytes = ", GetPerformanceAttributes("Memory", "Available Bytes") 0137 0138 if __name__=='__main__': 0139 ShowAllProcesses() 0140 print "Browsing for counters..." 0141 browse() 0142
Generated by PyXR 0.9.4