我正在尝试从同一行识别来电者。以下是一个例子:
def get_file():
caller_id = get_caller_id()
return open(caller_id, 'a+')
def write_content():
with get_file() as f1, get_file() as f2: # line with multiple callers
f1.write('123')
f2.write('456')
def fun():
write_content()
write_content()
write_content()
write_content()
write_content()
函数get_caller_id()
就是我想要的。它会为函数id
中的第一个和第二个get_file()
调用生成两个不同的write_content()
,但对于函数write_content()
中fun()
的所有5个调用都会生成,这两个get_file()
调用中的每一个都将在这5个write_content()
调用中返回一个相同文件的对象。
调用fun()
后,将只生成两个文件,一个包含内容'123123123123123',另一个包含'456456456456456'。返回的caller_id
只能对当前正在运行的会话保持一致,并且在python内核重新启动后caller_id
是否不一致无关紧要。
我尝试了inspect
模块:
def get_caller_id():
cur_frame = inspect.currentframe()
caller_frame = inspect.getouterframes(cur_frame)[2]
frame_obj = caller_frame[0]
line_no = caller_frame[2]
return '{}_{}'.format(id(frame_obj), line_no)
当一行中只有一个get_file()
来电时,此get_caller_id()
效果很好。但是对于来自同一行的多个呼叫者,它将生成相同的id,这不是我想要的。
我已经搜索了如何将调用者的列位置排成一行,但什么也没找到。这种定位是否可能?
感谢。
修改
以下是我正在做的事情:
class AutoSharedParams(object):
def __init__(self, dict_key='root', params_dict=None, init_value=None):
if params_dict is None:
params_dict = {}
self._params_dict = params_dict
self._dict_key = dict_key
if self._dict_key not in self._params_dict and init_value is not None:
self.x = init_value
def __call__(self, init_value=None, func=None):
caller_frame = inspect.getouterframes(inspect.currentframe())[1]
caller_id = id(caller_frame[0])
caller_ln = caller_frame[2]
key = '{}_c{}_l{}'.format(self._dict_key, caller_id, caller_ln)
if key not in self._params_dict:
if func:
init_value = func()
else:
init_value = None
return AutoSharedParams(dict_key=key, params_dict=self._params_dict, init_value=init_value)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return False
@property
def x(self):
if self._dict_key in self._params_dict:
return self._params_dict[self._dict_key]
else:
return None
@x.setter
def x(self, value):
self._params_dict[self._dict_key] = value
我使用lasagne
创建CNN(asp
是AutoSharedParams
的实例):
with asp(func=lambda: lasagne.init.HeNormal(gain='relu')) as w:
l = Conv2DLayer(l, num_filters=16, filter_size=(3, 3), W=w.x)
w.x = l.W
with asp(init_value=0) as w, asp(init_value=0) as b: # there are two calls in one line
l = Conv2DLayer(l, num_filters=16, filter_size=(3, 3), W=w.x, b=b.x)
w.x = l.W
b.x = l.b
我有很多类似但不同的代码,如上所述,我希望在此代码再次执行时分享这些创建的参数(w.x
,b.x
和许多其他代码)。最简单的方法是list.append(w)
和w=list.pop(0)
,但当代码中有不同的路径时,它将不兼容。所以我需要一把钥匙来标记它们。
答案 0 :(得分:0)
我认为你需要这样的东西:
>>> import inspect
>>> def f():
curframe = inspect.currentframe()
curframe = inspect.getouterframes(curframe, 2)
caller = curframe[1][3]
if caller == 'f1':
print "f() called f1()"
elif caller == "f2":
print "f() called f2()"
else:
print "f() called by an unknwon!"
>>> def f1():
f()
>>> def f2():
f()
>>> def f3():
f()
如下工作:
>>> f1()
f() called f1()
>>> f2()
f() called f2()
>>> f3()
f() called by an unknwon!
>>>
修改f()
以使不同的来电者具有不同的行为。