[英]How to send Python proxy objects across TCP
我在使用 Python 3.7.3 的 TCP 連接發送代理對象時遇到問題。 它們在本地工作正常,但是當兩個進程與 TCP 互連時,身份驗證密鑰設置不正確。
故事是這樣的:我在一個進程上有一個 class 的實例,我想從另一台機器上的另一個進程中引用它。 因此,我使用address=('', 50000)
在第一個進程上創建我的BaseManager
,取出其_authkey
的副本,並告訴另一個進程使用address=('whatever', 50000)
和authkey=...
創建一個BaseManager
authkey=...
並調用connect()
。 到目前為止,一切都很好。
第一個過程注冊了一些東西:
BaseManager.register('ManagerClass', ManagerClass)
BaseManager.register('managers', callable = lambda: managers)
managers
只是一本字典。 ManagerClass
有一個在字典中保存自我代理的方法,創建如下:
def autoself(self):
server = getattr(multiprocessing.current_process(), '_manager_server', None)
classname = self.__class__.__name__
if server:
for key,value in server.id_to_obj.items():
if value[0] == self:
token = multiprocessing.managers.Token(typeid=classname, address=server.address, id=key)
proxy = multiprocessing.managers.AutoProxy(token, 'pickle', authkey=server.authkey)
return proxy
else:
return self
順便說一句,如果我嘗試將ManagerClass
object 直接存儲在字典中然后傳輸它,我會得到
TypeError: can't pickle _thread.lock objects
不足為奇 - 這是一個復雜的 object 並且可能在某處有線程鎖。
因此,我將使用autoself
創建的自我代理存儲到字典中並傳輸它。
它幾乎可以工作,但是authkey
沒有在接收端正確設置,所以它不起作用。 看起來authkey
被設置為本地進程的authkey
,因為如果沒有指定authkey
或manager
,這是AutoProxy
中的默認值。
那么,如何指定呢? 字典由代理 object 表示,它調用遠程方法items()
,該方法返回包含AutoProxy
的腌制RebuildProxy
。 RebuildProxy
是否應該弄清楚它是從哪個管理器調用的,並從那里挑選出authkey
? 如果返回的代理 object 引用的 object 與持有字典的進程不同,該怎么辦? 不知道。
我已經通過破解BaseProxy
的__reduce__
方法來“修復”這個問題, get_spawning_popen()
是否始終傳輸其authkey
,並禁用AuthenticationString
中的檢查以防止它被腌制。 查看 Python 的multiprocessing/
目錄以理解我在說什么。
現在它起作用了。
不知道該怎么做。 如果我們有一個復雜的設置,有多個進程傳遞代理對象怎么辦? 沒有理由假設接收代理 object 的進程具有管理 object 的進程的 authkey; 它可能只有一個用於發送代理的進程的 authkey。 這是否意味着我們需要使用代理對象傳遞 authkeys? 還是我錯過了更好的方法來做到這一點?
我找到了一種解決問題的簡單方法:對每台機器上的每個進程使用相同的身份驗證密鑰。
當我導入多處理時,只需設置關鍵的第一件事:
import multiprocessing
multiprocessing.current_process().authkey = b"secret"
無需更改標准庫代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.