2016-04-30 62 views
3

我試圖從同一行識別來電者。下面是一個例子:如何從被調用者的同一行中識別多個呼叫者?

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 S爲第一和功能write_content()第二get_file()電話,但所有的功能fun() 5個通話write_content(),兩個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創建細胞神經網絡(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 

我有很多類似但不同的代碼,如上所述,我想分享這些cre (w.x,b.x和許多其他),當這段代碼再次通過。最簡單的方法是list.append(w)w=list.pop(0),但是如果代碼中有不同的路徑,它將不兼容。所以我需要一個鍵來標記它們。

+0

你究竟在試圖用這個做些什麼?爲什麼功能會根據調用函數的不同而有所不同,並且這不會使測試更加或者更不可能? – jonrsharpe

+0

@jonrsharpe我實際上在許多不同的地方創建了許多對象,並希望它們在下次調用該函數時自動存儲和共享。這些變量保存到字典中並從字典中恢復,並且此字典中使用的密鑰是調用的「caller_id」,它將創建相應的變量。當然,我可以手動爲每個變量分配一個鍵,但這會是多餘的,我不能保證鍵不會被重複。 – Texot

+1

您是否考慮過使用裝飾器將它們附加到調用者?你可以舉一個更清晰的例子,因爲我懷疑是XY問題。 – jonrsharpe

回答

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(),爲不同呼叫者不同的行爲。

+0

謝謝,EbraHim。對不起,我的問題描述不清。我已經可以定位調用者的行號,但是如果在一行中有多個調用,我不知道如何區分它們在調用者中。 – Texot

相關問題