djangoソース分析--00ソース分析ツール

18084 ワード

Pythonは非常に入門しやすいが、非常に精通しにくいプログラミング言語である.オブジェクト向け(継承集合、多態、組合せなど)、抽象(設計モード)、文法糖、メタプログラミング、コードの非常に柔軟な組み合わせが難しい.
私がボトルネックに直面して大量のフレームワークコードを読むことでプログラミングレベルを向上させる必要がある過程で、フレームワークコードが柔軟すぎるか抽象的であるため、ソースコードを読むだけで理解できないことが多いが、ログを加えて実行し、デバッグして現在の対象がどのようなクラスであるか、現在のオブジェクトにどのような属性があり、現在のオブジェクトが誰によって呼び出されているかを見る必要がある.
オープンソースフレームワークのソースコードを読むときによく使う2つの分析ツールを共有します.
デコレーション
呼び出し元のファイル位置パスとコード呼び出しが存在する行数を表示します.これにより、コード実行のソースがどこにあるかを1つ1つ追跡できます.すなわち,一般に用いられるシーンは,コード線形処理過程を理解することである.
utils.py
# -.- coding:utf-8 -.-
from __future__ import print_function


def findcaller(func):
    def wrapper(*args,**kwargs):
        import sys
        f=sys._getframe()
        filename=f.f_back.f_code.co_filename
        lineno=f.f_back.f_lineno
        print('{} {!s:<20} {} {} {} {} {}'.format(func.func_name, 'Called By ', filename, '', lineno, args, kwargs))
        return func(*args,**kwargs)
    return wrapper

使用方法
earth.py
# -.- coding:utf-8 -.-
import utils


@utils.findcaller
def golden():
    return 'metal'


@utils.findcaller
def wood():
    return golden()


@utils.findcaller
def water():
    return wood()


@utils.findcaller
def fire():
    return water()


@utils.findcaller
def land():
    return fire()


print(land())

出力結果
land Called By            C:/Users/zhengtong/earth.py  31 () {}
fire Called By            C:/Users/zhengtong/earth.py  28 () {}
water Called By            C:/Users/zhengtong/earth.py  23 () {}
wood Called By            C:/Users/zhengtong/earth.py  18 () {}
golden Called By            C:/Users/zhengtong/earth.py  13 () {}
metal

参考URL:Stansosleepyのブログ
           
内省関数
多くの場合、オープンソースフレームワークのドキュメントは、それぞれの方法がどういう意味なのか、どのように使われているのかを教えてくれません.通常、フレームワークのコンポーネント機能を使用するときは、メソッドを呼び出して返された結果を見て、その結果オブジェクトにどの呼び出し可能なメソッドが含まれているか、各メソッドがバインドされているクラスオブジェクトを分析することに慣れています.これらのプロパティオブジェクトを使用すると、フレームワーク全体の機能と理解をより全面的にすることができます.
utils.py
# -.- coding:utf-8 -.-
from __future__ import print_function

class ObjectAttrs(object):

    """
                 ,                                 。
    
       showed_list        ,            .
    
        :
    ObjectAttrs.show(    )
    """

    showed_list = []

    @classmethod
    def show(cls, _class, show_attr=True, show_doc=False, _parent_class=None):
        """
        :param _class:   ,     . 
        :param show_attr:     _class     attribute.                 
        :param show_doc:     _class   __doc__  .
        :param _parent_class:        ,     _class     .                 
        :return: 
        """

        def _show(class_name):
            if class_name in cls.showed_list:
                return
            else:
                cls.showed_list.append(class_name)

            parent_class_name = ' inherited by {}'.format(_parent_class) if _parent_class else ''
            blank_lines = '
' * 5 if show_attr else '' print(blank_lines, class_name, parent_class_name, sep='') if not show_attr: return for x in dir(class_name): if not show_doc: if x == '__doc__': continue try: attr_name = x attr_type = type(getattr(class_name, attr_name)) attr_object = getattr(class_name, attr_name) print('{!s:<60}{!s:<60}{}'.format(attr_name, attr_type, attr_object)) except: print('{!s:<60}{}'.format(attr_name, 'error')) _show(class_name=_class) parents = list(getattr(_class, '__bases__', '')) parents.append(getattr(_class, '__class__', '')) parents = [i for i in parents if i is not object and i is not type and i] for i in parents: cls.show(_class=i, _parent_class=_class, show_doc=show_doc, show_attr=show_attr)

ソースファイル
fox.py
# -.- coding:utf-8 -.-
import utils


class Base(object):

    def breathe(self):
        return 'breathe'


class Animal(Base):

    def run(self):
        return 'run'

    def walk(self):
        return 'walk'

    def sleep(self):
        return 'sleep'


class FoxManager(object):

    def find_other_fox(self):
        return 'find_other_fox'
        
    def drink(self):
        return 'drink water'
        
    def eat(self):
        return 'eat meat'


class Fox(Base):

    def __init__(self):
        self.name = 'aurora fox'
        self.sex = 'male'
        self.actions = FoxManager()
        

使用方法1:オブジェクトのすべての継承関係のみを表示
import utils
utils.ObjectAttrs.show(Fox(), show_attr=False)
#     
<__main__.fox object="" at="">
 inherited by <__main__.fox object="" at="">
 inherited by 

使用方法2:現在のオブジェクトのすべてのプロパティのみを表示
import utils
utils.ObjectAttrs.show(Fox(), show_parent=False)
#     
<__main__.fox object="" at="">
__class__                                                                                                  
__delattr__                                                 error
__dict__                                                                                                   {'name': 'aurora fox', 'actions': <__main__.foxmanager object="" at="">, 'sex': 'male'}
__format__                                                                           
__getattribute__                                            error
__hash__                                                    error
__init__                                                                                         >
__module__                                                                                                  __main__
__new__                                                                              
__reduce__                                                                           
__reduce_ex__                                                                        
__repr__                                                    error
__setattr__                                                 error
__sizeof__                                                                           
__str__                                                     error
__subclasshook__                                                                     
__weakref__                                                                                            None
actions                                                                                    <__main__.foxmanager object="" at="">
name                                                                                                        aurora fox
run                                                                                              >
sex                                                                                                         male
sleep                                                                                            >
walk                                                                                             >

使用方法3:現在のオブジェクトのすべてのプロパティを表示し、現在のオブジェクトのすべての継承関係を表示します.
import utils
utils.ObjectAttrs.show(Fox())
#     
<__main__.fox object="" at="">
__class__                                                                                                  
__delattr__                                                 error
__dict__                                                                                                   {'name': 'aurora fox', 'actions': <__main__.foxmanager object="" at="">, 'sex': 'male'}
__format__                                                                           
__getattribute__                                            error
__hash__                                                    error
__init__                                                                                         >
__module__                                                                                                  __main__
__new__                                                                              
__reduce__                                                                           
__reduce_ex__                                                                        
__repr__                                                    error
__setattr__                                                 error
__sizeof__                                                                           
__str__                                                     error
__subclasshook__                                                                     
__weakref__                                                                                            None
actions                                                                                    <__main__.foxmanager object="" at="">
name                                                                                                        aurora fox
run                                                                                              >
sex                                                                                                         male
sleep                                                                                            >
walk                                                                                             >





 inherited by <__main__.fox object="" at="">
__class__                                                                                                  
__delattr__                                                                                  
__dict__                                                                                              {'__module__': '__main__', '__doc__': None, '__init__': }
__format__                                                  error
__getattribute__                                                                             
__hash__                                                                                     
__init__                                                                                         
__module__                                                                                                  __main__
__new__                                                                              
__reduce__                                                  error
__reduce_ex__                                               error
__repr__                                                                                     
__setattr__                                                                                  
__sizeof__                                                  error
__str__                                                                                      
__subclasshook__                                                                     
__weakref__                                                                                   
run                                                                                              
sleep                                                                                            
walk                                                                                             





 inherited by 
__class__                                                                                                  
__delattr__                                                                                  
__dict__                                                                                              {'__module__': '__main__', 'run': , 'walk': , 'sleep': , '__dict__': , '__weakref__': , '__doc__': None}
__format__                                                  error
__getattribute__                                                                             
__hash__                                                                                     
__init__                                                                                     
__module__                                                                                                  __main__
__new__                                                                              
__reduce__                                                  error
__reduce_ex__                                               error
__repr__                                                                                     
__setattr__                                                                                  
__sizeof__                                                  error
__str__                                                                                      
__subclasshook__                                                                     
__weakref__                                                                                   
run                                                                                              
sleep                                                                                            
walk