如何从被叫方的同一行识别多个呼叫者?

时间:2016-04-30 09:14:41

标签: python

我正在尝试从同一行识别来电者。以下是一个例子:

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(aspAutoSharedParams的实例):

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.xb.x和许多其他代码)。最简单的方法是list.append(w)w=list.pop(0),但当代码中有不同的路径时,它将不兼容。所以我需要一把钥匙来标记它们。

1 个答案:

答案 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()以使不同的来电者具有不同的行为。