2012-08-22 5 views
7

मैं अपनी विस्तार लाइब्रेरी से संबंधित वस्तुओं के लिए पिकलिंग समर्थन को कार्यान्वित करना चाहता हूं। स्टार्टअप पर कक्षा सेवा का एक वैश्विक उदाहरण शुरू हुआ है। इन सभी वस्तुओं को कुछ सेवा विधि आमंत्रणों के परिणामस्वरूप उत्पादित किया जाता है और अनिवार्य रूप से इसका संबंध होता है। सेवा जानता है कि उन्हें बाइनरी बफर में क्रमबद्ध कैसे करें और बफर को ऑब्जेक्ट्स में कैसे deserialize करें।पायथन का __reduce __/copy_reg अर्थपूर्ण और स्टेटफुल अनपिक्लर

ऐसा प्रतीत होता है कि पायथन __ को कम करने के लिए मेरा उद्देश्य पूरा करना चाहिए - पिकलिंग समर्थन लागू करना। मैंने एक को कार्यान्वित करना शुरू कर दिया और महसूस किया कि अनपिकलर के साथ कोई समस्या है (पहला तत्व ओ टिपल __ को कम करने के लिए अपेक्षित होने की उम्मीद है)। इस अनपिक फ़ंक्शन को किसी ऑब्जेक्ट में इनपुट बफर को कनवर्ट करने में सक्षम होने के लिए सेवा की आवश्यकता होती है। इस मुद्दे को चित्रित करने के लिए यहां कुछ छद्म कोड दिया गया है:

class Service(object): 
    ... 
    def pickleObject(self,obj): 
     # do serialization here and return buffer 
     ... 

    def unpickleObject(self,buffer): 
     # do deserialization here and return new Object 
     ... 

class Object(object): 
    ... 
    def __reduce__(self): 
     return self.service().unpickleObject, (self.service().pickleObject(self),) 

टुपल में पहला तत्व नोट करें। पायथन पिकलर इसे पसंद नहीं करता है: यह कहता है कि यह examplemethod है और इसे मसालेदार नहीं किया जा सकता है। स्पष्ट रूप से पिकलर आउटपुट में दिनचर्या को स्टोर करने की कोशिश कर रहा है और फ़ंक्शन नाम के साथ सेवा उदाहरण चाहता है, लेकिन ऐसा नहीं है कि मैं ऐसा करना चाहता हूं। मैं नहीं चाहता (और वास्तव में नहीं कर सकता: सेवा पिकनीय नहीं है) सभी वस्तुओं के साथ सेवा स्टोर करने के लिए। मैं pickle.load को बुलाए जाने से पहले सेवा उदाहरण बनाना चाहता हूं और किसी भी तरह से उस उदाहरण को अनपिकलिंग के दौरान उपयोग किया जाता है।

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

class Service(object): 
    ... 
    def __init__(self): 
     ... 
     import copy_reg 
     copy_reg(mymodule.Object, self.pickleObject, self.unpickleObject) 

self.unpickleObject अब पहली बार एक पैरामीटर के रूप में एक बाध्य विधि लेने सेवा है और दूसरी के रूप में बफ़र। self.pickleObject भी अचार विधि और अचार के लिए वस्तु लेने के लिए बाध्य विधि है। copy_reg की आवश्यकता है कि pickleObject routine reducer semantic का पालन करना चाहिए और पहले जैसा ही tuple देता है। और यहां समस्या फिर से उभरी: मुझे पहले ट्यूपल तत्व के रूप में क्या वापस जाना चाहिए ??

class Service(object): 
    ... 
    def pickleObject(self,obj): 
     ... 
     return self.unpickleObject, (self.serialize(obj),) 

इस फ़ॉर्म में अचार फिर से शिकायत करता है कि यह examplemethod नहीं उठा सकता है। मैंने किसी को भी कोशिश नहीं की - यह इसे पसंद नहीं करता है। मैंने वहां कुछ डमी फ़ंक्शन लगाया। यह काम करता है - जिसका अर्थ है सीरियलाइजेशन चरण ठीक से चला गया है, लेकिन अनपिक्लिंग के दौरान यह अनमिक्लर के बजाय इस डमी फ़ंक्शन को कॉल करता है जिसे मैंने mymodule टाइप किया है। सेवा कन्स्ट्रक्टर में ऑब्जेक्ट करें।

तो अब मुझे नुकसान हुआ है। लंबी व्याख्या के लिए खेद है: मुझे नहीं पता था कि इस सवाल को कुछ पंक्तियों में कैसे पूछना है। मैं इस तरह मेरे सवालों का संक्षेप में प्रस्तुत कर सकते हैं:

  1. क्यों अर्थ copy_reg है मुझे pickleObject से unpickler दिनचर्या वापस जाने के लिए की आवश्यकता है, मैं एक स्वतंत्र रूप से एक रजिस्टर करने के लिए उम्मीद है?
  2. क्या अनपिकलर रूटीन पंजीकृत करने के लिए copy_reg.constructor इंटरफ़ेस को प्राथमिकता देने का कोई कारण है?
  3. मैं स्ट्रीम के अंदर एक के बजाय पंजीकृत अनपिकर का उपयोग करने के लिए अचार कैसे बना सकता हूं?
  4. मुझे pickleObject परिणाम मान के रूप में एक tuple में पहले तत्व के रूप में वापस क्या करना चाहिए? क्या कोई "सही" मूल्य है?
  5. क्या मैं इस पूरी चीज़ से सही तरीके से संपर्क करता हूं? क्या कोई अलग/सरल समाधान है?

आपके समय के लिए धन्यवाद।

गेनेडी

उत्तर

3

सबसे पहले, copy_reg मॉड्यूल आपको बहुत यहाँ मदद करने के लिए की संभावना नहीं है: यह मुख्य रूप से कक्षाओं के लिए सुविधाओं की तरह __reduce__ जोड़ने के लिए एक तरीका है कि उस विधि किसी भी विशेष योग्यता की पेशकश के बजाय की जरूरत नहीं है (है उदाहरण के लिए यदि आप कुछ पुस्तकालयों से वस्तुओं को चुनना चाहते हैं जो इसे मूल रूप से समर्थन नहीं देते हैं)।

__reduce__ द्वारा लौटाया जाने योग्य कॉल करने योग्य वातावरण में स्थानापन्न करने की आवश्यकता है जहां वस्तु को अनपिक किया जाना है, इसलिए एक उदाहरण विधि वास्तव में उपयुक्त नहीं है। के रूप में Pickle documentation में उल्लेख किया है:

unpickling माहौल में इस वस्तु (नीचे देखें) या तो एक वर्ग, एक प्रतिदेय एक "सुरक्षित निर्माता" के रूप में पंजीकृत होना चाहिए, या यह एक सच के साथ एक विशेषता __safe_for_unpickling__ होना आवश्यक है मूल्य।

तो तुम एक समारोह (नहीं विधि) में परिभाषित किया गया है, तो इस प्रकार है:

def _unpickle_service_object(buffer): 
    # Grab the global service object, however that is accomplished 
    service = get_global_service_object() 
    return service.unpickleObject(buffer) 

_unpickle_service_object.__safe_for_unpickling__ = True 

अब आप इस _unpickle_service_object समारोह अपने __reduce__ तरीकों की वापसी मान में इस्तेमाल कर सकते हैं ताकि आपके वस्तुओं नए माहौल के से जुड़ा हुआ अप्रचलित होने पर वैश्विक Service ऑब्जेक्ट।

+0

आपने ऊपर Q1 का उत्तर नहीं दिया था। –

+0

मैं कुछ ऐसा ही कर रहा था। भले ही मैंने सेवा उदाहरण वैश्विक कहा, यह बिल्कुल सही नहीं है। उत्पादन अनुप्रयोग में वास्तव में केवल एक उदाहरण होता है, लेकिन कुछ भी नहीं कहता कि यह वैश्विक है। और वास्तव में मेरे यूनिट परीक्षणों में मैं एक बार फिर से बना रहता हूं। मैंने अपने पैकेज में नियमित डीफ़ रजिस्टर (एसवीसी) और ग्लोबल मॉड्यूल लेवल वैरिएबल सेवा के साथ एक मॉड्यूल pickle.py लागू किया है जो रजिस्टर में सेट किया जा रहा है। यह नियमित रूप से copy_reg का उपयोग कर पिकलिंग/अनपिक्लिंग फ़ंक्शंस पंजीकृत करता है। यह दिनचर्या सेवा निर्माता से आती है। यद्यपि कुछ समस्याएं हैं: –

+0

1. यह केवल एक ही सेवा उदाहरण के लिए काम करता है। दूसरे शब्दों में, हमारे पास एक साथ मौजूद 2 अलग-अलग सेवाएं नहीं हो सकती हैं और दोनों में पिकेबल ऑब्जेक्ट्स 2. यह वैश्विक संदर्भ संभावित मेमोरी रिसाव का स्रोत है। मुझे इसे कब और कब साफ करना होगा? –

संबंधित मुद्दे