2013-05-04 11 views
35

मैं सीख रहा हूं कि अचार का उपयोग कैसे करें। मैंने एक नामांकित वस्तु बनाई है, इसे एक सूची में जोड़ा है, और उस सूची को चुनने की कोशिश की है। हालांकि, मैं निम्नलिखित त्रुटि मिलती है:एक नामांकित उदाहरण को सही तरीके से कैसे चुनें

pickle.PicklingError: Can't pickle <class '__main__.P'>: it's not found as __main__.P 

मैंने पाया है कि अगर मैं एक समारोह के अंदर यह लपेटकर बिना कोड भाग गया, यह पूरी तरह काम करता है। क्या फ़ंक्शन के अंदर लपेटते समय ऑब्जेक्ट को अचार करने के लिए कोई अतिरिक्त कदम आवश्यक है?

from collections import namedtuple 
import pickle 

def pickle_test(): 
    P = namedtuple("P", "one two three four") 
    my_list = [] 
    abe = P("abraham", "lincoln", "vampire", "hunter") 
    my_list.append(abe) 
    f = open('abe.pickle', 'w') 
    pickle.dump(abe, f) 
    f.close() 

pickle_test() 
+0

दुर्भाग्यवश, अचार नाम के साथ अच्छी तरह से काम नहीं कर रहा है। – Antimony

+1

@ एंटीमोनी: 'अचार' नामक कक्षाओं को ठीक से संभालती है; एक समारोह में परिभाषित वर्ग स्थानीय नामस्थान इतना नहीं है। –

+0

[पाइथन: पिकल प्रकार एक्स नहीं कर सकता, विशेषता लुकअप असफल] (http://stackoverflow.com/questions/4677012/python-cant-pickle-type-x-attribute-lookup-failed) – Air

उत्तर

51

नामित टपल बनाएं समारोह के बाहर:

यहाँ मेरी कोड है

from collections import namedtuple 
import pickle 

P = namedtuple("P", "one two three four") 

def pickle_test(): 
    my_list = [] 
    abe = P("abraham", "lincoln", "vampire", "hunter") 
    my_list.append(abe) 
    f = open('abe.pickle', 'w') 
    pickle.dump(abe, f) 
    f.close() 

pickle_test() 

अब pickle इसे पा सकते हैं; यह अब एक मॉड्यूल वैश्विक है। अनपिक्लिंग करते समय, सभी pickle मॉड्यूल को करना है __main__.P फिर से पता लगाना है। आपके संस्करण में, Pस्थानीय है, pickle_test() फ़ंक्शन पर, और यह आत्मनिर्भर या आयात योग्य नहीं है।

यह याद रखना महत्वपूर्ण है कि namedtuple() एक वर्ग कारखाना है; आप इसे पैरामीटर देते हैं और यह आपके लिए उदाहरण बनाने के लिए क्लास ऑब्जेक्ट देता है। pickle उदाहरणों में निहित डेटा स्टोर करता है, साथ ही मूल कक्षा के स्ट्रिंग संदर्भ को फिर से उदाहरणों का पुनर्निर्माण करने के लिए संदर्भित करता है।

+0

उत्कृष्ट! धन्यवाद। –

+4

तो, अगर मैं गतिशील रूप से 'नामित' बना रहा हूं तो क्या होगा क्योंकि मुझे रनटाइम तक फ़ील्ड नहीं पता? क्या इस मुद्दे को बाईपास करने का अभी भी कोई तरीका है? मैंने कक्षा के बाहर एक और तरीका बनाने की कोशिश की लेकिन यह काम नहीं किया। – Chuim

+4

@ कुहिम: इसे अपने मॉड्यूल ग्लोबल्स पर असाइन करें (एक ही नाम * के तहत 'ग्लोबल्स() 'मैपिंग प्राप्त करने के लिए) का उपयोग करें, और' पिकले 'इसे अभी भी ढूंढ सकता है। –

5

मैंने अपने प्रश्न को मुख्य उत्तर पर टिप्पणी के रूप में जोड़ने के बाद मुझे गतिशील रूप से निर्मित namedtuple अचार सक्षम बनाने की समस्या का समाधान करने का एक तरीका मिला। यह मेरे मामले में आवश्यक है क्योंकि मैं रनटाइम के दौरान फ़ील्ड की खोज कर रहा हूं (डीबी क्वेरी के बाद)।

def _CreateNamedOnMain(*args): 
    import __main__ 
    namedtupleClass = collections.namedtuple(*args) 
    setattr(__main__, namedtupleClass.__name__, namedtupleClass) 
    namedtupleClass.__module__ = "__main__" 
    return namedtupleClass 

ध्यान में रखना है कि namedtuple नाम (जो args द्वारा प्रदान की जाती है) __main__ में किसी अन्य सदस्य के ऊपर लिख सकता है द्वारा:

सभी मुझे क्या प्रभावी ढंग से __main__ मॉड्यूल पर ले जाकर बंदर पैचnamedtuple है आप सावधान नहीं हैं

+11

बस इसे 'ग्लोबल्स()' पर सेट करें: 'ग्लोबल्स() [nametupleClass .__ name__] = nametupleClass'। फिर '__module__' सेट करने के लिए * कोई ज़रूरत नहीं है *। –

+0

जब मैंने 'ग्लोबल्स() [nametupleClass .__ name__] = nametupleClass' की कोशिश की तो यह वास्तव में मुझे मेरी ऑब्जेक्ट को चुनने की अनुमति देता था, लेकिन जब मैंने अनपिक करने की कोशिश की तो उसे' nametupleClass' की आवश्यकता नहीं थी। मेरी सलाह है ** ** केवल एक शब्दकोश का उपयोग करें ** जब तक वे ऐसा करने के लिए पर्याप्त अचार नहीं बनाते। – Teque5

2

वैकल्पिक रूप से, आप क्रमबद्धता के लिए cloudpickle या dill उपयोग कर सकते हैं:

from collections import namedtuple 

import cloudpickle 
import dill 



def dill_test(dynamic_names): 
    P = namedtuple('P', dynamic_names) 
    my_list = [] 
    abe = P("abraham", "lincoln", "vampire", "hunter") 
    my_list.append(abe) 
    with open('deleteme.cloudpickle', 'wb') as f: 
     cloudpickle.dump(abe, f) 
    with open('deleteme.dill', 'wb') as f: 
     dill.dump(abe, f) 


dill_test("one two three four") 
1

मैं एक और धागा में this answer पाया। यह नामित tuple के नामकरण के बारे में सब कुछ है। यह मेरे लिए काम करता है:

group_t =   namedtuple('group_t', 'field1, field2') # this will work 
mismatched_group_t = namedtuple('group_t', 'field1, field2') # this will throw the error 
संबंधित मुद्दे