摘要:連接帶遠程管理器對象,該對象的地址在構造函數中支出。在當前進程中運行管理器服務器。啟動一個單的子進程,并在該子進程中啟動管理器服務器。如果無法序列號對象將引發異常。
上一篇文章:Python進程專題6:共享數據與同步
下一篇文章:Python進程專題8:分布集群的消息傳遞
進程不支持共享對象,上面描述的創建共享值和數組,但都是指定的特殊類型,對高級的Python對象(如:字典、列表、用戶自定義類的實例)不起作用。語法:還好multiprocessing模塊提供了一種使用共享對象的途徑:單前提是這些對象運行在所謂的【管理器】的控制之下。
管理器是獨立的子進程,其中存在真實的對象,并以服務器的形式運行,其他進程通過使用代理訪問共享對象,這些
代理作為管理器服務器的客戶端而運行。
m=Manager():在一個獨立的進程中創建運行的管理器,返回值是SyncManager(定義在multiprocess.managersa模塊中)類的實例。 m可以創建共享對象常用方法
在服務器上創建共享的Array實例并返回可以訪問它的代理。
在服務器上創建共享的threading.BoundedSemphore實例,并返回可訪問它的代理。
在服務器上創建共享的threading.Condition實例,并返回可訪問它的代理。 lock是m.Lock()或m.Rlock()方法創建的代理實例
在服務器上創建共享的dict(字典)實例,并返回可以訪問它的代理。
在服務器上創建共享的thread.Event實例,并返回可以訪問它的代理。
在服務器上創建共享的list實例,并返回可以訪問它的代理。
子服務器上創建共享的threading.Lock實例,并返回可訪問它的代理。
在服務器創建共享的namespace對象,并返回可以訪問它的代理。 namespace就是一個類似于Python模塊的對象。例如:如果n是一個命名空間代理,那么可以使用(.)賦值和讀取屬性, 例如:n.name=value 或value=n.name。但name的名稱十分重要,如果name以字母開頭,那么這個值就是管理器所擁有的共享對象的一部分, 所有其它進程均可訪問它,如果name以下劃線開頭,那么它只是代理對象的一部分,并不是共享。
在服務器上創建共享的Queue.Queue對象,并返回可訪問它的代理。
在服務器上創建共享的threading.Rlick對象,并返回可訪問它的代理。
在服務器上創建共享的threading.Semaphore對象,并返回可訪問它的代理。
在服務器上創建一個共享的Value對象,并返回可訪問它的代理。
#使用管理器創建一個在進程間共享的字典 import multiprocessing import time def watch(dict,event): while True: event.wait() print(dict) event.clear() if __name__=="__main__": #實例化一個管理器 m=multiprocessing.Manager() #在服務器上創建一個共享的字典,并返回可以調用它的代理 dict=m.dict() #在服務器上創建一個共享的Event event=m.Event() #啟動監視字典的進程 p=multiprocessing.Process(target=watch,args=(dict,event,)) #設置為后臺進程,隨主進程的銷毀而銷毀,該后臺進程無法創建新的線程 p.daemon=True p.start() #更新字典并通知監聽者 dict["name"]="mark" event.set() time.sleep(3) # 更新字典并通知監聽者 dict["age"] = 18 event.set() time.sleep(3) #終止進程和管理器 p.terminate() m.shutdown()
運行結果:
繼承BaseManager類,實現自定義對象的共享如果想要共享用戶自定義類的實例,則必須創建自定義管理器對象,為此,需要創建一個繼承自BaseManager類的類,其中BaseManager類定義在multiprocessing.managers子模塊中。
managers.BaseManager(address,authkey):用戶自定對象創建管理器服務器的基類。 address是一個可選的元組(hostname,port),用于指定服務器的網絡地址。如果忽略此參數,操作系統將簡單 的分配一個對應于某些空閑端口號的地址。 authkey是一個字符串,用于對連接到服務器的客戶端身份進行驗證。如果忽略此參數,將是喲個current_process().authkey的值。
假設myclass是一個繼承自BaseManager的類,可以使用以下類方法來創建用于返回代理給共享對象的方法。
myclass.register(typeid,callable,proxytype,exposed,method_to_typeid,create_method):使用管理器類注冊一種新的數據類型。 typeid:一個字符串,用于命名特殊類型的共享對象。這個字符串應該是有效的Python標識符。 callable:創建或返回要共享的實例的可調用對象。 proxytype:一個類,負責提供客戶端中藥使用的代理對象的實現,通常這些類是默認生成的,因此一般設置為None。 exposed:共享對象上方法名的序列,它將會公開給代理對象,如果省略此參數,將使用proxytype_exposed的值, 如果proxytype_expose未定義,序列將包含所有的公共方法(所有不以下劃線_開頭的可調用方法)。 method_to_typeid:從方法名稱到類型IDS的映射,這里的IDS用于指定哪些方法應該使用代理對象返回他們的結果, 如果某個方法在這個映射中找不到,將復制和返回它的返回值,如果method_to_typeid為None,將使用proxytype_method_to_typeid_的值。 create_method:一個布爾標志,用于指定是否在mgclass中創建名為typeid的方法,默認值為True。
從BaseManager類派生的管理器的實例m必須手動啟動才能運行。
屬性或者方法 | 解釋說明 |
---|---|
m.address | 元組(hostname,port),代表管理器服務器正在使用的地址。 |
m.connect() | 連接帶遠程管理器對象,該對象的地址在BaseManager構造函數中支出。 |
m.serve_forever() | 在當前進程中運行管理器服務器。 |
m.shutdown() | 關閉由start()啟動的管理器服務器。 |
m.start() | 啟動一個單的子進程,并在該子進程中啟動管理器服務器。 |
繼承自BaseProxy的類的實例具有以下方法:
proxy._callmethod(name,args,kwargs):調用代理引用對象上的方法name。 proxy._getvalue():返回調用者中引用對象的副本,如果這次調用是在另一個進程中, 那么引用對象將被序列化,發送給調用者,然后再進行反序列化。如果無法序列號對象將引發異常。
代碼:
#繼承BaseManager類,實現自定義對象的共享,利用代理公開屬性與方法 import multiprocessing from multiprocessing.managers import BaseManager from multiprocessing.managers import BaseProxy #普通需要共享的類,代理無法通過(.)這種形式直接訪問屬性 class MyClass(): def __init__(self,value): self.name=value def __repr__(self): return "MyClass(%s)"%self.name def getName(self): return self.name def setName(self,value): self.name=value def __add__(self,valuye): self.name+=valuye return self #通過自定義繼承BaseProxy來實現代理,從而正確的公開__add__方法,并使用特性(property)公開name屬性。 #BaseProxy來來自multiprocessing.managers模塊 class MyClassProxy(BaseProxy): #referent上公開的所有方法列表 _exxposed_=["__add__","getName","setName"] #實現代理的公共結接口 def __add__(self, value): self._callmethod("__add__",(value,)) return self @property def name(self): return self._callmethod("getName",()) @name.setter def name(self,value): self._callmethod("setName",(value,)) def __repr__(self): return "MyClass(%s)"%self.name def getName(self): return self.name def setName(self,value): self.name=value def __add__(self,valuye): self.name+=valuye return self class MyManager(BaseManager): pass #不使用代理 #MyManager.register("MyClass",MyClass) #使用代理 MyManager.register("MyClass",MyClass,proxytype=MyClassProxy) if __name__=="__main__": m=MyManager() m.start() #創建托管對象,此時知識創建了一個實例代理,無法直接訪問屬性,必須使用函數來訪問 #代理無法訪問特殊方法和下劃線(_)開頭的所有方法。 a=m.MyClass("mark") print(a) print(a.getName()) #不使用代理,下面兩條語句會異常 a.__add__("帥哥") print(a.name) #print(a.name) #a.__add__("帥哥")
結果:
MyClass(mark) mark mark帥哥
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42354.html
摘要:可以使用標準的索引切片迭代操作訪問它,其中每項操作均鎖進程同步,對于字節字符串,還具有屬性,可以把整個數組當做一個字符串進行訪問。當所編寫的程序必須一次性操作大量的數組項時,如果同時使用這種數據類型和用于同步的單獨大的鎖,性能將極大提升。 上一篇文章:Python進程專題5:進程間通信下一篇文章:Python進程專題7:托管對象 我們現在知道,進程之間彼此是孤立的,唯一通信的方式是隊...
摘要:代表網絡地址的元組或者代表域套接字的文件名,或者代表形式的字符串,代表遠程系統本地計算機的為上的一條命名管道。是一個整數,當參數指定了一個網絡連接時,對應于傳遞給套接字的方法的值,默認為。 上一篇文章:Python進程專題7:托管對象下一篇文章:Python進程專題9:關于進程的實用工具函數 使用multiprocessing模塊的程序不僅可以于運行在同一計算機的其它程序進行消息傳遞...
摘要:上一篇文章進程專題完結篇多進程處理的一般建議下一篇文章線程專題多線程使用的必要性進程線程進程能夠完成多任務,比如在一個電腦上可以運行多個軟件。由于占用資源少,也使得多線程程序并發比較高。 上一篇文章:Python進程專題完結篇:多進程處理的一般建議下一篇文章:Python線程專題1:多線程使用的必要性 進程VS線程 進程:能夠完成多任務,比如在一個電腦上可以運行多個軟件。線程:也能夠...
摘要:上一篇文章進程專題繼承來創建進程下一篇文章進程專題進程間通信當我們需要創建大量的進程時,利用模塊提供的來創建進程。關閉進程池,不再接受進的進程請求,但已經接受的進程還是會繼續執行。 上一篇文章:Python進程專題3:繼承Process來創建進程下一篇文章:Python進程專題5:進程間通信 當我們需要創建大量的進程時,利用multiprocessing模塊提供的Pool來創建進程。 ...
摘要:類常用屬性布爾值,指示進程是否是后臺進程。當創建它的進程終止時,后臺進程會自動終止。進程的整數退出指令。如果進程仍然在運行,它的值為,如果值為負數,就表示進程由信號所終止。 上一篇文章:Python進程專題1:fork():創建子進程、getpid()、getppid()下一篇文章:Python進程專題3:繼承Process來創建進程 由于fork()無法對Windows使用,而py...
閱讀 3768·2023-04-25 21:09
閱讀 3127·2021-10-20 13:48
閱讀 2940·2021-09-24 10:25
閱讀 2930·2021-08-21 14:08
閱讀 1789·2019-08-30 15:56
閱讀 975·2019-08-30 15:52
閱讀 1841·2019-08-29 14:11
閱讀 3561·2019-08-29 11:01