Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# coding: UTF-8
""" Monitoring """
class Monitoring(dict):
@classmethod
def _printCodeInfo(cls, cur_frame):
import inspect
bac_frame = cur_frame.f_back # この関数の呼び出し元のフレームオブジェクトを取得。
bac_frame_co = bac_frame.f_code
# print("呼び出し元関数名 = {}".format(bac_frame_co.co_name))
bac_frame_info = inspect.getframeinfo(bac_frame) # フレームオブジェクトのフレームレコードを取得。
# print("そのフレームレコードから得たソースコードのリスト = {}".format(bac_frame_info.code_context))
# print("そのフレームから得た行番号 = {}".format(bac_frame.f_lineno))
print('@@ %03d : func %s - %s' % (bac_frame.f_lineno, bac_frame_co.co_name, bac_frame_info.code_context))
#print('==== %x' % (id(bac_frame_co.__self__)))
#print("cur local variables {}".format(cur_frame.f_locals))
#print("bac local variables {}".format(bac_frame.f_locals))
@classmethod
def _printStackInfo(cls, label):
import inspect
framerecords = inspect.stack()
# print(" == stack {}".format(framerecords))
if len(framerecords) > 2 :
framerecord = framerecords[2] # 呼び出し元フレーム
arginfo = inspect.getargvalues(framerecord[0]) # 呼び出し元(先頭)から引き数情報を取得
if 'self' in arginfo.locals:
print(" >>>> %s id = %x " % (label, id(arginfo.locals['self'])))
else:
print(" >>>> %s NONE" % label)
@classmethod
def printArgInfo(cls, *args):
# print("@@@@@ args = %s" % format(args))
for arg in args:
if(isinstance(arg, Monitoring)):
print('called_with: id = %x' % id(arg))
else:
print('called_with: value = %s %s ' % (format(arg), type(arg)))
def __new__(cls, *args):
import inspect
cls._printCodeInfo(inspect.currentframe())
# print('called __new__: id = %x %s' % (id(cls), format(cls)))
print('called __new__: id = %x (%s)' % (id(cls), cls.__name__))
cls._printStackInfo('sender')
obj = super(Monitoring, cls).__new__(cls, args)
print(' >>>> instance id = %x' % id(obj))
return obj
def __getattr__(self, key):
import inspect
self.__class__._printCodeInfo(inspect.currentframe())
value = self.__getitem__(key)
if(isinstance(value, Monitoring)):
print('called __getattr__: id = %x (%s, %s = id %x)' % (id(self), key, value, id(value)))
else:
print('called __getattr__: id = %x (%s, %s = %s)' % (id(self), key, value, type(value)))
self.__class__._printStackInfo('run_on')
return value
def __setattr__(self, key, value):
import inspect
self.__class__._printCodeInfo(inspect.currentframe())
result = self.__setitem__(key, value)
if(isinstance(value, Monitoring)):
print('called __setattr__: id = %x (%s, %s = id %x)' % (id(self), key, value, id(value)))
else:
print('called __setattr__: id = %x (%s, %s = %s)' % (id(self), key, value, type(value)))
self.__class__._printStackInfo('run_on')
return result
def __getattribute__(self, key):
# print("====================== key = %s" % (key))
if key == '__getitem__': # これは getter アクセスの副作用
pass
v = object.__getattribute__(self, key)
if key == 'printCodeInfo':
return v.__get__(None, self) # 内部処理はフィルタする
if hasattr(v, '__get__'):
import inspect
self.__class__._printCodeInfo(inspect.currentframe())
print('called __getattribute__: id = %x (%s AS function)' % (id(self), key))
self.__class__._printStackInfo('sender')
return v.__get__(None, self)
if key == '__getitem__': # これは getter アクセスの副作用
pass
elif key == '__setitem__': # これは setter アクセスの副作用
pass
elif key == '__class__': # これは上の printCodeInfo を呼び出すための __class__ 呼び出しの副作用
pass
else:
print('called __getattribute__: id = %x (%s AS variable)' % (id(self), key))
return v
# ================ トレースする対象となるオブジェクト
class Foo(Monitoring):
def __init__(self):
print "--------"
self.bar = Bar()
print "--------"
print self.bar.a
print "--------"
self.bar.pr()
print "--------"
self.a = 0 # Foo
class Bar(Monitoring):
def __init__(self):
self.a = 0 # Bar
def pr(self):
print "- 123 -"
class Boo(Monitoring):
def pr(self):
print "test"
# ================ ここから主プログラム
print("##########")
obj1 = Foo()
print("##########")
print(obj1.a)
print("##########")
obj2 = Boo()
obj2 = Boo()
print("##########")
@yyasuda

This comment has been minimized.

Copy link
Owner Author

yyasuda commented Jan 19, 2016

まあこれだけじゃあ何のことか分からないでしょうが、、、ともかく実行結果を。。。

##########
@@ 125 : func <module> - ['obj1 = Foo()\n']
called __new__: id = 7fad0b507860 (Foo)
    >>>> sender NONE
    >>>> instance id = 10e80fbe0
--------
@@ 103 : func __init__ - ['        self.bar = Bar()\n']
called __new__: id = 7fad0b507c10 (Bar)
    >>>> sender id = 10e80fbe0 
    >>>> instance id = 10e80fd08
@@ 113 : func __init__ - ['        self.a = 0 # Bar\n']
called __setattr__: id = 10e80fd08 (a, 0 = <type 'int'>)
    >>>> run_on id = 10e80fd08 
@@ 103 : func __init__ - ['        self.bar = Bar()\n']
called __setattr__: id = 10e80fbe0 (bar, {'a': 0} = id 10e80fd08)
    >>>> run_on id = 10e80fbe0 
--------
@@ 105 : func __init__ - ['        print self.bar.a\n']
called __getattr__: id = 10e80fbe0 (bar, {'a': 0} = id 10e80fd08)
    >>>> run_on id = 10e80fbe0 
@@ 105 : func __init__ - ['        print self.bar.a\n']
called __getattr__: id = 10e80fd08 (a, 0 = )
    >>>> run_on id = 10e80fbe0 
0
--------
@@ 107 : func __init__ - ['        self.bar.pr()\n']
called __getattr__: id = 10e80fbe0 (bar, {'a': 0} = id 10e80fd08)
    >>>> run_on id = 10e80fbe0 
@@ 107 : func __init__ - ['        self.bar.pr()\n']
called __getattribute__: id = 10e80fd08 (pr AS function)
    >>>> sender id = 10e80fbe0 
- 123 -
--------
@@ 109 : func __init__ - ['        self.a = 0 # Foo\n']
called __setattr__: id = 10e80fbe0 (a, 0 = )
    >>>> run_on id = 10e80fbe0 
##########
@@ 127 : func  - ['print(obj1.a)\n']
called __getattr__: id = 10e80fbe0 (a, 0 = )
    >>>> run_on NONE
0
##########
@@ 129 : func  - ['obj2 = Boo()\n']
called __new__: id = 7fad0b507fc0 (Boo)
    >>>> sender NONE
    >>>> instance id = 10e80fe30
@@ 130 : func  - ['obj2 = Boo()\n']
called __new__: id = 7fad0b507fc0 (Boo)
    >>>> sender NONE
    >>>> instance id = 10e9a9050
##########

これでつまり実行時のオブジェクトへのアクセスをログに残して、これを可視化してやろうというわけです。。。

@yyasuda

This comment has been minimized.

Copy link
Owner Author

yyasuda commented Jan 19, 2016

sample8_01

@yyasuda

This comment has been minimized.

Copy link
Owner Author

yyasuda commented Jan 19, 2016

もひとつ。実際のコードとの対照はこんな感じ。
sample8_01x

@yyasuda

This comment has been minimized.

Copy link
Owner Author

yyasuda commented Jan 21, 2016

なお上のダイアグラム的な図は手描き。ソースコードとの対照図も手描きです。
あくまで学生向けの説明資料。。。。頑張って実装してくれると良いのだけれど。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.