Last active
May 18, 2016 08:10
-
-
Save yyasuda/7cc6dd4e8332f1f16ec4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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("##########") |
なお上のダイアグラム的な図は手描き。ソースコードとの対照図も手描きです。
あくまで学生向けの説明資料。。。。頑張って実装してくれると良いのだけれど。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
もひとつ。実際のコードとの対照はこんな感じ。