首页 > 代码库 > 分析特定类的python脚本

分析特定类的python脚本

今天接触了下pyUSB,事先没看对象内部成员资料,直接用python的dir函数看了看pyUSB的内部构成。突然间想到自己可不可以写个简单的脚本,利用dir或其他函数遍历某个对象内部的所有成员,并打印出来成树状图的形式?于是写了如下对象分析程序:

使用方法 :

import matplotlib.pyplot as pltimport AnalysisClassm = AnalysisClass.AnalysisClass()m.analysisObject(plt.Arrow, plt.Arrow, plt.txt, levelEnd=3)

调用analysisObject即可分析matplotlib的pyplot库内部的成员,并把所有成员函数、成员类以及各成员的__doc__前两行作为概述打印出来。上面的plt.Arrow是要分析的对象,’plt.Arrow’是要分析对象的名称字符串,’plt.txt’是用来保存分析结果的文件名,levelEnd用来指定递归的深度。

上面调用得到的结果:

 

clip_image002

省略若干行

clip_image004

代码概述:

程序核心很简单,就是递归地用dir()函数得到对象的所有成员,对于以下划线开头的内部成员不予处理,其他的如常量(一般全大写)、成员函数、成员类等的名字则保存起来,然后在以这些成员为对象递归地获取下一层的成员列表。

详细程序:

import typesclass AnalysisClass:    def __init__(self):        self.level= 0        self.file = None        self.constNum=[]        self.funcNum = []    def _levelTreePrint(self, strs, isConst=False):        levelTab=self.level*4*         levelStrHead =[i for i in levelTab]        if self.level != 0:#             strs = str(self.funcNum[-1])+strs            for i in range(self.level):                if (not isConst) and self.funcNum[i] == 1:                                    continue                else:                    levelStrHead[i*4+1] = |            levelStrHead[((self.level-1)*4+2):] = [-,-]            levelStrHead = ‘‘.join(levelStrHead)            levelStr = levelStrHead+strs        else:            levelStr = strs        print levelStr        if self.file != None:            self.file.writelines(levelStr+\n)#     def _isListOrTuple(self, cla):#         if type(cla)==types.ListType or type(cla)==types.TupleType:#             return True#         else:#             return False    def _hasAvailableCla(self, cla):        mems = dir(cla)        constMem=[]        claOrFuncMem = []        constMaxLen = 0        funcMaxLen = 0        for i in mems:            lenI = len(i)            if i[0] == _: # No inner function or inner constants                continue             if i.isupper():                if lenI>constMaxLen:                    constMaxLen = lenI                constMem.append(i)            elif i[0:2]!=__ and i[-2:]!=__:# No buildin functions                if lenI>funcMaxLen:                    funcMaxLen = lenI                claOrFuncMem.append(i)        return (constMem, constMaxLen, claOrFuncMem, funcMaxLen)    def _printConstMem(self, cla, constMem, constMaxLen):        loc_var = locals()              for i in loc_var.iteritems():            if id(i[1]) == id(cla):                cla_loc_name = i[0]        for i in constMem:            tmp = eval(cla_loc_name+.+i)            i = i.ljust(constMaxLen+1,  )#             if type(tmp)==types.IntType:#                 i = i+"(%d)"%tmp#             else:#                 i = i+"(NOT AN INT NUMBER)"+str(type(tmp))            i = i + "(%s)"%str(tmp)            self._levelTreePrint(i, isConst=True)            self.constNum[-1] -= 1            def _printClaOrFuncMem(self,cla, cla_name, funcMaxLen, claOrFuncMem):        loc_var = locals()              for i in loc_var.iteritems():            if id(i[1]) == id(cla):                cla_loc_name = i[0]        for i in claOrFuncMem:            iMem = cla_loc_name+.+i            iMemReName = cla_name+.+i            try:                if None!=eval(iMem):                    self._analysisClass(eval(iMem),iMemReName, maxClaNameLen = funcMaxLen)                    self.level -= 1                else:                    self._levelTreePrint(cla_name.split(.)[-1]+.+i+"--‘Nothing‘")            except Exception,e:                pass            self.funcNum[-1] -= 1                def _analysisClass(self, cla, cla_name, maxClaNameLen = 0):        if hasattr(cla, "__doc__"):            doc = str(cla.__doc__).split(\n)            if len(doc)>=2:                doc = doc[0]+doc[1]            else:                doc = doc[0]        else:            doc =              if self.level!=0 and maxClaNameLen!=0:            sNameTmp = cla_name.split(.)            extraLen = len(sNameTmp[-2])            sName = sNameTmp[-2]+.+sNameTmp[-1]            cla_name_tmp = sName.ljust(extraLen+maxClaNameLen+1, )        else:            cla_name_tmp = cla_name        self._levelTreePrint(cla_name_tmp+:+str(type(cla))+3*-+"\""+doc+"\"")        self.level += 1        if self.level == self.levelEnd:            return         (constMem, constMaxLen, claOrFuncMem, funcMaxLen) = self._hasAvailableCla(cla)        if constMaxLen != 0:            self.constNum.append(len(constMem))            self._printConstMem(cla, constMem, constMaxLen)            self.constNum.pop()        if funcMaxLen != 0:            self.funcNum.append(len(claOrFuncMem))            self._printClaOrFuncMem(cla, cla_name, funcMaxLen, claOrFuncMem)            self.funcNum.pop()        else:            return        #===========================================================================    # Analysis the stucture of ‘obj‘.This function will list out the members of the object as    # a tree.    # @param obj - object,can be class,module,package,etc    # @param obj_name - object name string,should be same to the actual name of ‘obj‘    # @param file_name - If you want to store the analysis info to a txt file,set this param     #                    of your file name    # @paramm levelEnd - set the recursion limits.The analysisObject function will recursively    #                    enum all the members of the ‘obj‘,when the recursion depth equals levelEnd    #                    the function will stop automatically    #    # Using:    # import AnalysisClass    # import matplotlib.pyplot as plt    # m = AnalysisClass.AnalysisClass()    # m.analysisObject(plt.Annotation, ‘plt.Annotation‘, ‘plt.txt‘, levelEnd=4)    # Written by Liu.2014-07-25    #===========================================================================    def analysisObject(self, obj, obj_name, file_name=None, levelEnd=3):        if file_name != None:            self.file = open(file_name, w)        self.levelEnd = levelEnd        self._analysisClass(obj, obj_name, levelEnd)        if self.file !=None:            self.file.close()