6

मुझे एक नया defaultdict प्रॉक्सी ऑब्जेक्ट को लागू करने का प्रयास करने में कुछ परेशानी हो रही है। documentation थोड़ा डरा हुआ है, इसलिए मुझे यकीन नहीं है कि इस बारे में सही तरीके से कैसे जाना है।multiprocessing.managers subclassing.BaseProxy

मैं Manager उदाहरण से उपलब्ध प्रकारों की सूची में defaultdict जोड़ना चाहता हूं। आप multiprocessing.mangers.BaseManager

class Manager(BaseManager): 
    pass 

मैं तो multiprocessing.managers.BaseProxy की मेरी उपवर्ग के घर में बनाया से अपने खुद के ठूंठ प्रबंधक शेयर multiprocessing.Manager पर Manager.register विधि का उपयोग नहीं कर सकते हैं तो मैं कर दिया है defaultdict (मैं शुरू में पराग-कोश ठूंठ जायें जो कि होने का प्रयास किया उपवर्ग दोनों defaultdict और BaseProxy लेकिन यह है कि काम करने के लिए नहीं लगता था यहाँ मैं वर्तमान में क्या है:।।

class ProxyDefaultDict(BaseProxy): 
    def __init__(self, default_factory=None, *args, **kwargs): 
     self.__data = defaultdict(default_factory) 
     super().__init__(*args, **kwargs) 

    def _callmethod(self, methodname, args=(), kwds={}): 
     return getattr(self.__data, methodname)(*args, **kwds) 

    def _getvalue(self): 
     return self.__data.copy() 

    def __repr__(self): 
     return self.__data.__repr__() 

    def __str__(self): 
     return self.__data.__str__() 

Manager.register('defaultdict', ProxyDefaultDict) 

अंतिम लक्ष्य एक साझा शब्दकोश जो सुरक्षित रूप से प्रक्रियाओं और धागे भर में keyed ताले का प्रयोग करता है के लिए है वह फिर मैं कैसे छवि यह initialised किया जाएगा का एक उदाहरण है:

if __name__ == '__main__': 
    m = Manager() 
    d = m.defaultdict(m.Lock) 
    with d['named_lock']: 
     print('holding the lock') 

हालांकि, मैं कुछ समस्याओं पर पहुंच जाते हैं:

  1. BaseManager का एक उपवर्ग एक संदर्भ प्रबंधक यानी के माध्यम से ही initalizable हो रहा है with Manager() as m। इस मामले में मैं m = Manager() का उपयोग करूंगा - multiprocessing.Manager की अनुमति देता है। दुनिया का अंत नहीं, लेकिन अधिक उत्सुक क्यों यह मामला है और यदि यह एक संकेत है तो मैं कुछ गलत तरीके से कर रहा हूं।

  2. multiprocessing.managers.BaseManager उप-वर्गीकरण भी आप multiprocessing.Manager से डिफ़ॉल्ट पंजीकृत मान खो देते हैं। इस मामले में मुझे अपने प्रबंधक के लिए प्रॉक्सी लॉक पुनः पंजीकृत करने की आवश्यकता है (जिसे मैं ऐसा करने के अपेक्षित तरीके से भी अनिश्चित हूं)। क्या यह केवल multiprocessing.Manager को उपclass सुरक्षित है।

  3. अंत में, मेरे ProxyDefaultDict मुझे अपने __init__ को साफ़ रूप से ओवरराइड करने की अनुमति नहीं देता है। और जब मैं सबक्लासिंग करता हूं तो BaseProxy.__init__ पर कॉल न करने से थक गया हूं। समस्या यह है कि बेसप्रॉक्सी भी स्थितित्मक तर्क स्वीकार करता है। मुझे लगता है कि default_factory को केवल एक कुंजीपटल तर्क देने का तरीका है, लेकिन यह अनुमानित इंटरफ़ेस को defaultdict पर बदलता है और मुझे लगता है कि मैं यहां कुछ गलत तरीके से कर रहा हूं। Manager.Lock जैसे अन्य प्रकार स्थितित्मक तर्क स्वीकार करने में सक्षम हैं।

किसी भी मदद के लिए धन्यवाद।

उत्तर

3

स्रोत कोड देखने के बाद, इसका एक छोटा सा संशोधन मेरे लिए डिफ़ॉल्ट डिफॉल्ट प्रकार प्रॉक्सी प्राप्त करने के लिए काम करता है (डिक्टप्रोक्सी में निर्मित कैसे बनाया जाता है) के आधार पर।

from collections import defaultdict 

from multiprocessing.managers import MakeProxyType, SyncManager 

DefaultDictProxy = MakeProxyType("DefaultDictProxy", [ 
    '__contains__', '__delitem__', '__getitem__', '__len__', 
    '__setitem__', 'clear', 'copy', 'default_factory', 'fromkeys', 
    'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 
    'update', 'values']) 

SyncManager.register("defaultdict", defaultdict, DefaultDictProxy) 
# Can also create your own Manager here, just using built in for simplicity 

if __name__ == '__main__': 
    with SyncManager() as sm: 
     dd = sm.defaultdict(list) 
     print(dd['a']) 
     # [] 

व्यक्तिगत तौर पर मैं यह आसान टूल पहले से ही प्रदान की जाती का उपयोग करके, यहां तक ​​कि यह कैसे अपने आप को उपवर्ग के बारे में चिंता करने की जरूरत नहीं है कि लगता है।

हालांकि, मुझे नहीं लगता कि यह आपको डिफ़ॉल्ट लॉक परिदृश्य बनाने की अनुमति देगा जो आप खोज रहे हैं। मल्टीप्रोसेसिंग ताले केवल विरासत में रहने के लिए डिज़ाइन किए गए हैं, और आम तौर पर ताले को मसालेदार नहीं किया जा सकता है, जो प्रॉक्सी के माध्यम से डेटा प्रकारों को स्थानांतरित करने की आवश्यकता है।उदाहरण:

from multiprocessing import Lock 

    m = SyncManager() 
    m.start() 
    d = m.defaultdict(Lock) 
    print(d['named_lock']) 
    m.shutdown() 

एक रनटाइम त्रुटि बढ़ा देंगे:

RuntimeError: Lock objects should only be shared between processes through inheritance 
+0

आह, हाँ, लगता है कि आप '' register' SyncManager' नहीं बल्कि 'Manager', धन्यवाद पर कॉल कर सकते हैं। जब मैं डिफ़ॉल्ट रूप से लॉक का उपयोग करता हूं और उपयोग करता हूं तो मुझे आपके लिए एक अलग त्रुटि मिलती है। प्रबंधित लॉक का उपयोग करने का प्रयास करते समय उदा। 'm.defaultdict (m.Lock) 'मुझे एक' TypeError मिलता है: सुरक्षा कारणों से त्रुटि के लिए एक प्रमाणीकरण स्ट्रिंग ऑब्जेक्ट को अनदेखा किया जाता है। एक अप्रबंधित ताला के साथ मुझे 'अनसुलझा करने योग्य संदेश मिलता है: (' #RETURN ', <लॉक (स्वामी = कोई नहीं)>) '। पायथन 3.4 पर चल रहा है। मैंने सोचा होगा कि अगर एक ताला लगाया जा सकता है तो इसे मसाला जा सकता है। – freebie

+0

हाँ मुझे लगता है कि 3.6 में एक अद्यतन त्रुटि/पहचान का तरीका है। अगर मैं थ्रेडिंग ताले का उपयोग करने की कोशिश करता हूं तो मुझे वही त्रुटि मिलती है। कुछ अन्य विचार हैं https://stackoverflow.com/questions/17960296/trouble-using-a-lock-with-multiprocessing-pool-pickling-error इसके आस-पास पहुंचने के लिए। – CasualDemon