2014-12-30 41 views
4

我正在使用python請求庫並試圖保持會話。Python取消了一個對象,其中有一個類實例

由於我的主機上有多個IP,爲了使會話綁定到特定的IP,我創建了以下方法。

class SourceAddressAdapter(HTTPAdapter): 
    def __init__(self, source_address, **kwargs): 
     self.source_address = source_address 
     super(SourceAddressAdapter, self).__init__(**kwargs) 

    def init_poolmanager(self, connections, maxsize, block=False): 
     self.poolmanager = PoolManager(num_pools=connections, 
            maxsize=maxsize, 
            block=block, 
            source_address=self.source_address) 

下面的代碼片用於調用這個類:

r = requests.Session() 
r.mount('http://', SourceAddressAdapter((self.ip,0))) 
r.mount('https://', SourceAddressAdapter((self.ip,0))) 

安裝http和https協議到該適配器後,我用泡菜的對象持續到redis的如下:

session = pickle.dumps(r) 
redis.hset('sessions',id,session) 

當我嘗試取消會話對象時發生問題:

s=redis.hget('sessions', id) 
pickle.loads(s) 


Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.7/pickle.py", line 1382, in loads 
    return Unpickler(file).load() 
    File "/usr/lib/python2.7/pickle.py", line 858, in load 
    dispatch[key](self) 
    File "/usr/lib/python2.7/pickle.py", line 1217, in load_build 
    setstate(state) 
    File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 114, in __setstate__ 
    block=self._pool_block) 
    File "network_driver.py", line 158, in init_poolmanager 
    source_address=self.source_address) 
AttributeError: 'SourceAddressAdapter' object has no attribute 'source_address' 

它抱怨SourceAddressAdapter沒有source_address屬性。在將此類SourceAddressAdapter添加到我的會話之前,序列化運行良好。

所以我想這是定製類酸洗/取出問題。


UPDATE:

它的工作原理我加入__getstate____setstate__方法後,進入SourceAddressAdapter

def __getstate__(self): 
    # it calls HTTPAdapter's __getstate__() 
    state = super(SourceAddressAdapter, self).__getstate__() 
    state['source_address'] = self.source_address 
    return state 

def __setstate__(self,state): 
    self.source_address = state['source_address'] 
    # Call HTTPAdapter's __setstate__ function to pack the attributes in parent class 
    super(SourceAddressAdapter, self).__setstate__(state) 
+0

SourceAddressAdapter位於何處? –

+0

SourceAddressAdapter位於network_driver.py中,另一個文件main.py調用pickle – Yifei

+0

主調用酸洗和拆卸? –

回答

5

我相信問題是HTTPAdapter類定義了一個__setstate__方法。這個函數在取消時被調用,並將實例恢復到pickled狀態。但是,HTTPAdapter對您的source_address屬性一無所知,因此該屬性不會被恢復(或者甚至可能不會在第一個地方進行醃製)。

要解決這個問題,你需要重寫__setstate__功能,有點像這樣:

def __setstate__(self, state): 
    self.source_address= state['source_address'] # do this before calling __setstate__ 
    HTTPAdapter.__setstate__(self, state) 

而且,正如前面提到的,你可能還需要重寫__getstate__功能,以便source_address被醃漬。

+0

謝謝Rawing,我更新了我的問題,添加了__getstate__和__setstate__以將picker對象中的source_address持久化 – Yifei

相關問題