2008-09-20 9 views
5

मैं कुछ गैर- ASCIIutf-8 इनकोडिंग उस पर डेटा के साथ एक स्ट्रिंग चर बना कर शुरूआत:क्यों यूनिकोड() मेरे ऑब्जेक्ट पर स्ट्रिंग() का उपयोग करता है केवल बिना एन्कोडिंग के?

>>> text = 'á' 
>>> text 
'\xc3\xa1' 
>>> text.decode('utf-8') 
u'\xe1' 

का उपयोग unicode() उस पर त्रुटियों को जन्म देती है ...

>>> unicode(text) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
        ordinal not in range(128) 

। .. लेकिन अगर मुझे एन्कोडिंग पता है तो मैं इसे दूसरे पैरामीटर के रूप में उपयोग कर सकता हूं:

>>> unicode(text, 'utf-8') 
u'\xe1' 
>>> unicode(text, 'utf-8') == text.decode('utf-8') 
True 

अब अगर मैं एक वर्ग कि __str__() विधि में इस पाठ देता है:

>>> class ReturnsEncoded(object): 
...  def __str__(self): 
...   return text 
... 
>>> r = ReturnsEncoded() 
>>> str(r) 
'\xc3\xa1' 

unicode(r) उस पर str() उपयोग करने के लिए लगता है, के बाद से यह ऊपर unicode(text) रूप में एक ही त्रुटि को जन्म देती है: अब तक

>>> unicode(r) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: 
        ordinal not in range(128) 

सब कुछ योजनाबद्ध है!

लेकिन कोई भी कभी भी उम्मीद करेंगे के रूप में, unicode(r, 'utf-8') भी कोशिश नहीं करेगा:

>>> unicode(r, 'utf-8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: coercing to Unicode: need string or buffer, ReturnsEncoded found 

क्यों? यह असंगत व्यवहार क्यों? क्या यह एक बग है? क्या इसका इरादा है? बहुत अजीब

उत्तर

7

व्यवहार भ्रमित, लेकिन आकस्मिक प्रतीत होता है। मैं यहां Python Built-In Functions documentation (संस्करण 2.5 के लिए) से यूनिकोड दस्तावेज़ों की पूरी तरह से पुन: पेश करता हूं।2, मैं इस बारे में के रूप में):

यूनिकोड ([वस्तु [, एन्कोडिंग [, त्रुटियों]]])

वापसी निम्नलिखित विधियों में से एक का उपयोग कर वस्तु के यूनिकोड स्ट्रिंग संस्करण:

यदि एन्कोडिंग और/या त्रुटियां दी जाती हैं, तो यूनिकोड() ऑब्जेक्ट को डीकोड करेगा जो या तो 8-बिट स्ट्रिंग या एक वर्ण बफर एन्कोडिंग के लिए कोडेक का उपयोग कर सकता है। एन्कोडिंग पैरामीटर एक स्ट्रिंग एक एन्कोडिंग का नाम दे रहा है; अगर एन्कोडिंग ज्ञात नहीं है, लुकअप त्रुटि उठाई गई है। त्रुटि प्रबंधन त्रुटियों के अनुसार किया जाता है; यह इनपुट एन्कोडिंग में अमान्य वर्णों के उपचार को निर्दिष्ट करता है। यदि त्रुटियां 'सख्त' ( डिफ़ॉल्ट) हैं, तो 'अनदेखा' का मान त्रुटियों को चुपचाप अनदेखा कर देता है, और 'प्रतिस्थापन' का मान आधिकारिक यूनिकोड प्रतिस्थापन चरित्र, का कारण बनता है यू + एफएफएफडी, इनपुट वर्णों को प्रतिस्थापित करने के लिए उपयोग किया जा सकता है जो डीकोड नहीं हो सकता है। codecs मॉड्यूल भी देखें।

यदि कोई वैकल्पिक पैरामीटर नहीं दिया गया है, तो यूनिकोड() स्ट्र() के व्यवहार की नकल करेगा, सिवाय इसके कि यह 8-बिट तारों के बजाय यूनिकोड तार लौटाता है। अधिक सटीक, यदि ऑब्जेक्ट एक यूनिकोड स्ट्रिंग या सबक्लास है तो यह बिना किसी अतिरिक्त डिकोडिंग के यूनिकोड स्ट्रिंग को वापस कर देगा।

ऐसी वस्तुओं के लिए जो __unicode __() विधि प्रदान करते हैं, यह को इस विधि को यूनिकोड स्ट्रिंग बनाने के लिए तर्क के बिना कॉल करेगा। अन्य सभी ऑब्जेक्ट्स के लिए, 8-बिट स्ट्रिंग संस्करण या प्रतिनिधित्व अनुरोध किया गया है और फिर 'सख्त' मोड में डिफ़ॉल्ट एन्कोडिंग के लिए कोडेक का उपयोग करके यूनिकोड स्ट्रिंग में परिवर्तित किया गया है।

संस्करण 2.0 में नया। संस्करण 2.2 में बदला गया: __unicode __() के लिए समर्थन जोड़ा गया।

इसलिए, जब आप unicode(r, 'utf-8') कहते हैं, यह एक 8 बिट स्ट्रिंग या पहले तर्क के रूप में एक चरित्र बफर की आवश्यकता है, तो यह __str__() पद्धति का उपयोग करके अपने वस्तु coerces, और कहा कि utf-8 कोडेक का उपयोग डिकोड करने के लिए प्रयास करता है। utf-8 के बिना, unicode() फ़ंक्शन आपके ऑब्जेक्ट पर __unicode__() विधि के लिए ढूंढता है, और इसे नहीं ढूंढता, __str__() विधि को कॉल करता है, जैसा कि आपने सुझाव दिया है, यूनिकोड में कनवर्ट करने के लिए डिफ़ॉल्ट कोडेक का उपयोग करने का प्रयास कर रहा है।

4

unicode आपके टेक्स्ट के एन्कोडिंग का अनुमान नहीं लगाता है। यदि आपका ऑब्जेक्ट खुद को unicode के रूप में प्रिंट कर सकता है, तो __unicode__() विधि को परिभाषित करें जो यूनिकोड स्ट्रिंग देता है।


रहस्य नहीं है कि वास्तव में unicode(r) ही बुला नहीं है __str__() है। इसके बजाय, यह __unicode__() विधि की तलाश में है। __unicode__() का डिफ़ॉल्ट कार्यान्वयन __str__() पर कॉल करेगा और फिर ascii वर्णसेट का उपयोग करके इसे डीकोड करने का प्रयास करेगा। जब आप एन्कोडिंग पास करते हैं, unicode() अपेक्षा करता है कि पहली वस्तु कुछ ऐसा हो जो डीकोड किया जा सके - यानी basestring का उदाहरण है। क्योंकि यह ascii के रूप में डिकोड करने के लिए अगर मैं उत्तीर्ण नहीं होते हैं 'utf-8' की कोशिश करता है


व्यवहार अजीब है। लेकिन अगर मैं पारित 'utf-8' यह एक अलग त्रुटि देता है ...

ऐसा इसलिए है क्योंकि जब आपके द्वारा निर्दिष्ट "utf-8", यह एक स्ट्रिंग की तरह वस्तु के रूप में पहले पैरामीटर डीकोड किया जा करने के लिए व्यवहार करता है। इसके बिना, यह पैरामीटर को एक ऑब्जेक्ट के रूप में यूनिकोड पर ले जाने के लिए व्यवहार करता है।

मुझे भ्रम को समझ में नहीं आता है। यदि आप जानते हैं कि ऑब्जेक्ट की text विशेषता हमेशा यूटीएफ -8 एन्कोडेड होगी, तो बस __unicode__() परिभाषित करें और फिर सब कुछ ठीक काम करेगा।

+0

मुझे लगता है कि मैंने खुद को स्पष्ट नहीं किया होगा। मुझे पता है कि। मेरा मतलब यह है कि क्यों यूनिकोड (आर) के यूनिकोड (आर, 'यूटीएफ -8') से अलग व्यवहार है ??? – nosklo

+0

व्यवहार अजीब है क्योंकि अगर मैं 'utf-8' पास नहीं करता हूं तो यह ascii के रूप में डीकोड करने का प्रयास करता है। लेकिन अगर मैं 'utf-8' पास करता हूं तो यह एक अलग त्रुटि देता है ... – nosklo

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