अजगर के साथ एक अजगर 2 वस्तु को अनपिक करना 3


129

मैं सोच रहा था कि क्या कोई वस्तु लोड करने का एक तरीका है जिसे Python 2.4 में लिया गया था, Python 3.4 के साथ।

मैं इसे प्राप्त करने के लिए कंपनी की विरासत कोड की एक बड़ी राशि पर 2to3 चला रहा हूं।

ऐसा करते समय, फ़ाइल चलाते समय मुझे निम्न त्रुटि मिलती है:

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
    d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

विवाद में चुने हुए ऑब्जेक्ट को देखते हुए, यह एक dictमें है dict, जिसमें चाबियाँ और प्रकार के मूल्य हैं str

तो मेरा सवाल यह है: क्या एक वस्तु को लोड करने का एक तरीका है, मूल रूप से अजगर 2.4 में लिया गया है, अजगर 3.4 के साथ?


1
क्या अजगर 2.4 में jsonमॉड्यूल है? शायद आप एक 2.4 स्क्रिप्ट लिख सकते हैं जो ऑब्जेक्ट को unpickles करता है और इसे एक json ऑब्जेक्ट के रूप में बचाता है, और फिर एक 3.4 स्क्रिप्ट लिखता है जो json ऑब्जेक्ट पढ़ता है और इसे 3.4-संगत अचार ऑब्जेक्ट के रूप में सहेजता है। यह एक बार का ऑपरेशन होगा जो आप अपनी सभी अचार फाइलों पर चलाते हैं।
केविन

मैं इसी तरह की रेखाओं के साथ सोच रहा था, यह देखते हुए कि ये ऐसी डिक हैं जिन्हें मैं समझता हूं कि मैं बस sys.stdout को एक फ़ाइल में बदल सकता हूं और उन्हें प्रिंट कर सकता हूं, लेकिन मैं यह देखना चाहता हूं कि क्या मैं उन्हें पहले लोड कर सकता हूं
NDevox

संबंधित सवाल विशेष रूप से डेटाटाइम के साथ करने के लिए: stackoverflow.com/questions/24805105/…
जॉन वाई

जवाबों:


189

आपको बताना होगा pickle.load()कि पायथन बाइटिंग डेटा को पायथन 3 स्ट्रिंग्स में कैसे बदलना है, या आप pickleउन्हें बाइट के रूप में छोड़ने के लिए कह सकते हैं ।

डिफ़ॉल्ट ASCII के रूप में सभी स्ट्रिंग डेटा को आज़माने और डिकोड करने के लिए है, और यह डिकोडिंग विफल हो जाती है। pickle.load()प्रलेखन देखें :

वैकल्पिक कीवर्ड तर्क fix_imports , एन्कोडिंग और त्रुटियाँ हैं , जिनका उपयोग Python 2 द्वारा उत्पन्न अचार स्ट्रीम के लिए संगतता समर्थन को नियंत्रित करने के लिए किया जाता है। यदि Fix_imports सत्य है, तो Python 3 में उपयोग किए गए नए नाम के लिए अचार पुराने Python 2 नामों को मैप करने का प्रयास करेगा। एन्कोडिंग और त्रुटियां अचार को बताती हैं कि पायथन 2 द्वारा उठाए गए 8-बिट स्ट्रिंग इंस्टेंस को कैसे डीकोड किया जाए; क्रमशः 'ASCII' और 'सख्त' के लिए ये डिफ़ॉल्ट हैं। एन्कोडिंग 'बाइट' बाइट्स वस्तुओं के रूप में इन 8 बिट स्ट्रिंग उदाहरणों को पढ़ने के लिए हो सकता है।

एन्कोडिंग सेट करना latin1आपको डेटा को सीधे आयात करने की अनुमति देता है:

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

लेकिन आपको यह सत्यापित करने की आवश्यकता होगी कि आपके किसी भी तार को गलत कोडेक का उपयोग करके डिकोड नहीं किया गया है; लैटिन -1 किसी भी इनपुट के लिए काम करता है क्योंकि यह बाइट मानों को 0-255 से पहले 256 यूनिकोड कोड पॉइंट पर सीधे मैप करता है।

विकल्प के साथ डेटा को लोड करना होगा encoding='bytes', और bytesबाद में सभी कुंजी और मान को डीकोड करना होगा ।

ध्यान दें कि 3.6.8, 3.7.2 और 3.8.0 से पहले पायथन संस्करणों तक, पायथन 2 datetimeऑब्जेक्ट डेटा की अनप्लिकिंग तब तक टूट जाती है जब तक आप उपयोग नहीं करते हैं encoding='bytes'


1
इसे पायथन 2 के साथ कैसे पिछड़ा बनाया जा सकता है? जाहिर है, एन्कोडिंग तर्क पायथन 2 के लिए मौजूद नहीं है।
एपिकैडव

2
@EpicAdv: आपको पायथन 2 के साथ इस कोड को संगत बनाने की आवश्यकता नहीं है; इस सवाल यह है कि अजगर 2 अचार पायथन 3. ड्रॉप में लोड करने के बारे में है encodingकीवर्ड को पूरी तरह अजगर 2 के लिए
मार्टिन पीटर्स

10
@EpicAdv: आप एक अचार_ दत्तक डिक्शनरी बना सकते हैं जो या तो अजगर 2 के लिए खाली है या 'encoding': 'latin1'अचार में ** अचार_ दत्तक भेजना है। इस तरह इसे दोनों संस्करणों में चलना चाहिए।
pipefish

@ पिपीफ़िश - चतुर, लेकिन कहीं न कहीं आपको यह पता लगाना होगा कि आप किस संस्करण का उपयोग कर रहे हैं, इसलिए आप सीधे तौर पर कॉल को अलग-अलग कर सकते हैं (संस्करण के साथ एक और अतिरिक्त तर्क के बिना)। लेकिन कम से कम आपको एपिकएडव की टिप्पणी का सार मिल गया, जिसे मार्टिज़न की टिप्पणी बिल्कुल भी संबोधित नहीं करती है।
जॉन वाई

2
मुझे पता है कि datetimeटिप्पणी इस उत्तर का मुख्य जोर नहीं थी, लेकिन भविष्य के पाठकों के लिए, मैं यह encoding='latin-1'बताना चाहता हूं कि पायथन 3 के "फिक्स्ड" संस्करणों को अभी भी पायथन 2 डेटासेट को अनपिक करने की आवश्यकता है। यदि आपका अचार वाला पायथन 2 डेटा लैटिन -1 के अलावा किसी अन्य चीज़ में एन्कोडेड डेटेटाइम और बायस्ट्रेस दोनों को शामिल करने के लिए होता है, तो आप अभी भी encoding='bytes'सभी का उपयोग करने से बेहतर हो सकते हैं।
जॉन वाई

15

encoding='latin1'कुछ मुद्दों का उपयोग करने के कारण जब आपकी वस्तु में सुन्न सरणियाँ होती हैं।

का उपयोग करना encoding='bytes'बेहतर होगा।

उपयोग करने की पूरी व्याख्या के लिए कृपया इस उत्तर को देखेंencoding='bytes'


कौन से मुद्दे? मुझे क्या सावधान रहना चाहिए? उपयोग bytesबाइट्स में तार बनाता है (), इसलिए मैं latin1यदि संभव हो तो पसंद करता हूं , लेकिन यह मेरे लिए स्पष्ट नहीं है कि समस्या क्या है।
गुलज़ार

2
@ sreeragh-ar: क्या आप उन समस्याओं का उदाहरण दे सकते हैं जिनका आपने सामना किया? मेरे पास एक दो-आयामी numpy.ndarray(संख्या 1.14) है, जिसका उपयोग पायथन 2.7 में किया गया है cPickle.dumps(), और pickle.loads(..., encoding='latin1')ठीक काम करता है।
djvg

@djvg मुझे उन मुद्दों का सामना करना पड़ा जब मुझे छवियों को छवि स्ट्रिंग के रूप में अचार करना था और उन्हें हटाना नहीं था। यहां कोड पाया जा सकता है। gist.github.com/sreeragh-ar/70205db3a43badbfa69f758faa898be3
श्रीरेग एआर

@ गुलज़ार कृपया समस्या के लिए उपरोक्त सार देखें। चित्र अप्रकाशित होने के बाद दूषित हो रहे थे।
श्रीरंग एआर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.