विभिन्न उत्तरों से बिट्स और टुकड़ों के लिए धन्यवाद, मुझे लगता है कि हम एक स्पष्टीकरण को सिलाई कर सकते हैं।
एक यूनिकोड स्ट्रिंग, u '\ xe9' को प्रिंट करने का प्रयास करके, पायथन ने स्पष्ट रूप से उस स्ट्रिंग को एन्कोड करने का प्रयास किया जो वर्तमान में sys.stdout.encoding में संग्रहीत एन्कोडिंग योजना का उपयोग कर रहा है। पाइथन वास्तव में पर्यावरण से इस सेटिंग को चुनता है, जिससे इसे शुरू किया गया है। यदि इसे पर्यावरण से उचित एन्कोडिंग नहीं मिल पाती है, तभी यह अपने डिफ़ॉल्ट ASCII पर वापस लौटता है।
उदाहरण के लिए, मैं एक बैश शेल का उपयोग करता हूं, जो यूटीएफ -8 में डिफॉल्ट को एन्कोडिंग करता है। यदि मैं इससे पायथन शुरू करता हूं, तो यह उस सेटिंग का उपयोग करता है:
$ python
>>> import sys
>>> print sys.stdout.encoding
UTF-8
आइए एक पल के लिए पायथन शेल से बाहर निकलें और कुछ बोगस एन्कोडिंग के साथ बैश के वातावरण को सेट करें:
$ export LC_CTYPE=klingon
# we should get some error message here, just ignore it.
फिर अजगर शेल को फिर से शुरू करें और सत्यापित करें कि यह वास्तव में अपने डिफ़ॉल्ट एएससीआई एन्कोडिंग पर वापस जाता है।
$ python
>>> import sys
>>> print sys.stdout.encoding
ANSI_X3.4-1968
बिंगो!
यदि आप अब कुछ यूनिकोड चरित्र को एएससीआई के बाहर आउटपुट करने का प्रयास करते हैं, तो आपको एक अच्छा त्रुटि संदेश मिलना चाहिए
>>> print u'\xe9'
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9'
in position 0: ordinal not in range(128)
पायथन से बाहर निकलें और बैश शेल को त्यागें।
अब हम देखेंगे कि पायथन आउटपुट स्ट्रिंग्स के बाद क्या होता है। इसके लिए हम सबसे पहले एक ग्राफिक टर्मिनल के भीतर एक बैश शेल शुरू करेंगे (मैं गनोम टर्मिनल का उपयोग करता हूं) और हम आईएसओ-8859-1 उर्फ लैटिन -1 के साथ आउटपुट को डिकोड करने के लिए टर्मिनल सेट करेंगे (ग्राफिक टर्मिनलों में आमतौर पर कैरेक्टर सेट करने का विकल्प होता है उनके ड्रॉपडाउन मेनू में से एक में एन्कोडिंग )। ध्यान दें कि यह वास्तविक शेल पर्यावरण के एन्कोडिंग को नहीं बदलता है , यह केवल उस तरीके को बदलता है जो टर्मिनल खुद को आउटपुट देगा जिसे वह दिया गया है, वेब ब्राउज़र जैसा थोड़ा सा करता है। इसलिए आप शेल के वातावरण से स्वतंत्र रूप से टर्मिनल की एन्कोडिंग को बदल सकते हैं। आइए फिर शेल से पायथन शुरू करें और सत्यापित करें कि sys.stdout.encoding शेल पर्यावरण एन्कोडिंग (मेरे लिए UTF-8) पर सेट है:
$ python
>>> import sys
>>> print sys.stdout.encoding
UTF-8
>>> print '\xe9' # (1)
é
>>> print u'\xe9' # (2)
é
>>> print u'\xe9'.encode('latin-1') # (3)
é
>>>
(1) अजगर बाइनरी स्ट्रिंग को आउटपुट करता है, जैसे ही टर्मिनल इसे प्राप्त करता है और लैटिन -1 कैरेक्टर मैप के साथ इसके मूल्य का मिलान करने की कोशिश करता है। लैटिन -1 में, 0xe9 या 233 वर्ण "é" देता है और इसलिए टर्मिनल प्रदर्शित करता है।
(2) अजगर ने जो भी योजना वर्तमान में sys.stdout.encoding में सेट की गई है, इस उदाहरण में "यूटीएफ -8" के साथ यूनिकोड स्ट्रिंग को निहित करने का प्रयास किया है । UTF-8 एन्कोडिंग के बाद, परिणामी बाइनरी स्ट्रिंग '\ xc3 \ xa9' है (बाद में स्पष्टीकरण देखें)। टर्मिनल इस तरह स्ट्रीम प्राप्त करता है और लैटिन -1 का उपयोग करके 0xc3a9 को डिकोड करने का प्रयास करता है, लेकिन लैटिन -1 0 से 255 तक जाता है और इसलिए, केवल एक बार में 1 बाइट को डिकोड करता है। 0xc3a9 2 बाइट लंबा है, लैटिन -1 डिकोडर इसलिए इसे 0xc3 (195) और 0xa9 (169) के रूप में व्याख्या करता है और 2 वर्णों को उत्पन्न करता है: Ã और ©।
(3) अजगर ने यूनिकोड कोड पॉइंट u '\ xe9' (233) को लैटिन -1 स्कीम के साथ एनकोड किया। लैटिन -1 कोड पॉइंट्स रेंज 0-255 है और उस रेंज के भीतर यूनिकोड जैसा ही चरित्र बताता है। इसलिए, उस रेंज में यूनिकोड कोड पॉइंट लैटिन -1 में एन्कोड किए जाने पर समान मान प्राप्त करेगा। तो u-\ 'xe9' (233) लैटिन -1 में एन्कोडेड बाइनरी स्ट्रिंग '\ xe9' भी पैदा करेगा। टर्मिनल उस मूल्य को प्राप्त करता है और उसे लैटिन -1 चरित्र मानचित्र पर मेल करने की कोशिश करता है। केस (1) की तरह, यह "é" देता है और यही प्रदर्शित होता है।
चलिए अब टर्मिनल की एन्कोडिंग सेटिंग्स को ड्रॉपडाउन मेनू से यूटीएफ -8 में बदलते हैं (जैसे आप अपने वेब ब्राउज़र की एन्कोडिंग सेटिंग्स को बदलेंगे)। पायथन को रोकने या शेल को पुनरारंभ करने की आवश्यकता नहीं है। टर्मिनल की एन्कोडिंग अब पायथन से मेल खाती है। आइए फिर से छपाई का प्रयास करें:
>>> print '\xe9' # (4)
>>> print u'\xe9' # (5)
é
>>> print u'\xe9'.encode('latin-1') # (6)
>>>
(4) अजगर बाइनरी स्ट्रिंग के रूप में आउटपुट है। टर्मिनल UTF-8 के साथ उस स्ट्रीम को डिकोड करने का प्रयास करता है। लेकिन UTF-8 का मान 0xe9 नहीं है (बाद में स्पष्टीकरण देखें) और इसलिए इसे यूनिकोड कोड बिंदु में परिवर्तित करने में असमर्थ है। कोई कोड बिंदु नहीं मिला, कोई वर्ण मुद्रित नहीं हुआ।
(5) अजगर sys.stdout.encoding में जो कुछ भी है, उसके साथ यूनिकोड स्ट्रिंग को स्पष्ट रूप से एनकोड करने का प्रयास करता है । फिर भी "UTF-8"। परिणामी बाइनरी स्ट्रिंग '\ xc3 \ xa9' है। टर्मिनल धारा प्राप्त करता है और UTF-8 का उपयोग करके 0xc3a9 को डिकोड करने का प्रयास करता है। यह कोड कोड 0xe9 (233) देता है, जो यूनिकोड चरित्र मानचित्र पर प्रतीक "é" को इंगित करता है। टर्मिनल "é" प्रदर्शित करता है।
(6) पायथन ने लैटिन -1 के साथ यूनिकोड स्ट्रिंग को एन्कोड किया, यह एक बाइनरी स्ट्रिंग को उसी मान '\ xe9' के साथ देता है। फिर से, टर्मिनल के लिए यह केस (4) जैसा ही है।
निष्कर्ष: - पायथन अपने डिफ़ॉल्ट एन्कोडिंग पर विचार किए बिना, गैर-यूनिकोड स्ट्रिंग्स को कच्चे डेटा के रूप में आउटपुट करता है। टर्मिनल सिर्फ उन्हें प्रदर्शित करने के लिए होता है अगर इसकी वर्तमान एन्कोडिंग डेटा से मेल खाती है। - अजगर sic.stdout.encoding में निर्दिष्ट योजना का उपयोग करके एन्कोडिंग के बाद यूनिकोड के तारों का उत्पादन करता है। - पायथन को शेल के वातावरण से सेटिंग मिलती है। - टर्मिनल अपनी एन्कोडिंग सेटिंग्स के अनुसार आउटपुट प्रदर्शित करता है। - टर्मिनल की एन्कोडिंग शेल से स्वतंत्र है।
यूनिकोड, यूटीएफ -8 और लैटिन -1 पर अधिक विवरण:
यूनिकोड मूल रूप से वर्णों की एक तालिका है जहां कुछ प्रतीकों (बिंदुओं) को पारंपरिक रूप से कुछ प्रतीकों को इंगित करने के लिए सौंपा गया है। उदाहरण के लिए, यह निर्णय लिया गया है कि कुंजी 0xe9 (233) 'é' प्रतीक की ओर इशारा करता है। ASCII और यूनिकोड 0 से 127 तक एक जैसे कोड पॉइंट्स का उपयोग करते हैं, जैसे कि लैटिन -1 और यूनिकोड 0 से 255 तक करते हैं। यानी, ASCII में 0x41 अंक, लैटिन -1 और यूनिकोड, 0x8 अंक 'में' लैटिन -1 और यूनिकोड, 0xe9 लैटिन -1 और यूनिकोड में 'é' की ओर इशारा करते हैं।
इलेक्ट्रॉनिक उपकरणों के साथ काम करते समय, यूनिकोड कोड बिंदुओं को इलेक्ट्रॉनिक रूप से प्रस्तुत करने के लिए एक कुशल तरीके की आवश्यकता होती है। यही एन्कोडिंग योजनाएँ हैं। विभिन्न यूनिकोड एन्कोडिंग योजनाएं मौजूद हैं (utf7, UTF-8, UTF-16, UTF-32)। सबसे सहज और सीधे आगे एन्कोडिंग दृष्टिकोण यूनिकोड मानचित्र में कोड बिंदु के मूल्य को अपने इलेक्ट्रॉनिक रूप के लिए मूल्य के रूप में उपयोग करना होगा, लेकिन यूनिकोड में वर्तमान में एक लाख से अधिक कोड बिंदु हैं, जिसका अर्थ है कि उनमें से कुछ के लिए 3 बाइट की आवश्यकता होती है व्यक्त की है। पाठ के साथ कुशलता से काम करने के लिए, 1 से 1 मानचित्रण अव्यवहारिक होगा, क्योंकि इसके लिए आवश्यक होगा कि सभी कोड बिंदुओं को अंतरिक्ष की समान मात्रा में संग्रहीत किया जाए, जिसमें न्यूनतम 3 बाइट प्रति वर्ण हों, उनकी वास्तविक आवश्यकता की परवाह किए बिना।
अधिकांश एन्कोडिंग योजनाओं में अंतरिक्ष की आवश्यकता के बारे में कमियां हैं, सबसे अधिक आर्थिक वाले सभी यूनिकोड कोड बिंदुओं को कवर नहीं करते हैं, उदाहरण के लिए एससीआई केवल पहले 128 को कवर करता है, जबकि लैटिन -1 पहले 256 को कवर करता है। अन्य जो अधिक व्यापक अंत होने की कोशिश करते हैं। बेकार, चूंकि उन्हें आवश्यकता से अधिक बाइट्स की आवश्यकता होती है, यहां तक कि आम "सस्ते" पात्रों के लिए भी। उदाहरण के लिए, यूटीएफ -16 प्रति चरित्र की न्यूनतम 2 बाइट्स का उपयोग करता है, जिसमें एससीआई रेंज ('बी' जो 65 है, अभी भी यूटीएफ -16 में 2 बाइट्स भंडारण की आवश्यकता है) शामिल हैं। UTF-32 और भी अधिक बेकार है क्योंकि यह 4 बाइट्स में सभी वर्णों को संग्रहीत करता है।
UTF-8 के साथ चतुराई से हल किया गया है, एक योजना के साथ बाइट रिक्त स्थान की एक चर राशि के साथ कोड बिंदुओं को स्टोर करने में सक्षम है। इसकी एन्कोडिंग रणनीति के भाग के रूप में, UTF-8 लेस कोड उन बिट्स के साथ इंगित करता है जो संकेत देते हैं (संभवतः डिकोडर्स के लिए) उनकी अंतरिक्ष आवश्यकताओं और उनकी सीमाओं को दर्शाता है।
यूसीएफ -8 इकाइसी रेंज में यूनिकोड कोड पॉइंट की एन्कोडिंग (0-127):
0xxx xxxx (in binary)
- x का वास्तविक स्थान एन्कोडिंग के दौरान कोड बिंदु "स्टोर" करने के लिए आरक्षित है
- अग्रणी 0 एक ध्वज है जो UTF-8 डिकोडर को इंगित करता है कि इस कोड बिंदु को केवल 1 बाइट की आवश्यकता होगी।
- एन्कोडिंग पर, UTF-8 उस विशिष्ट रेंज में कोड बिंदुओं के मूल्य को नहीं बदलता है (यानी UTF-8 में 65 एन्कोडेड भी 65 है)। यह ध्यान में रखते हुए कि यूनिकोड और एएससीआईआई भी एक ही सीमा में संगत हैं, यह संयोग से UTF-8 और ASCII को भी उस सीमा में संगत बनाता है।
उदाहरण के लिए 'बी' के लिए यूनिकोड कोड बिंदु '0x42' या बाइनरी में 0100 0010 है (जैसा कि हमने कहा, यह ASCII में भी ऐसा ही है)। UTF-8 में एन्कोडिंग के बाद यह बन जाता है:
0xxx xxxx <-- UTF-8 encoding for Unicode code points 0 to 127
*100 0010 <-- Unicode code point 0x42
0100 0010 <-- UTF-8 encoded (exactly the same)
यूटीएफ -8 यूनिकोड कोड अंक 127 (गैर-एससीआईआई) से ऊपर एन्कोडिंग:
110x xxxx 10xx xxxx <-- (from 128 to 2047)
1110 xxxx 10xx xxxx 10xx xxxx <-- (from 2048 to 65535)
- प्रमुख बिट्स '110', यूटीएफ -8 डिकोडर को इंगित करता है जो एक कोड पॉइंट की शुरुआत 2 बाइट्स में एन्कोडेड होता है, जबकि '1110' 3 बाइट्स को इंगित करता है, 11110 4 बाइट्स को इंगित करता है और आगे।
- भीतरी '10' ध्वज बिट्स का उपयोग एक आंतरिक बाइट की शुरुआत को इंगित करने के लिए किया जाता है।
- फिर से, एक्स के निशान को उस स्थान पर चिह्नित करें जहां एन्कोडिंग के बाद यूनिकोड कोड बिंदु मान संग्रहीत है।
उदाहरण के लिए 'é' यूनिकोड कोड बिंदु 0xe9 (233) है।
1110 1001 <-- 0xe9
जब UTF-8 इस मान को एन्कोड करता है, तो यह निर्धारित करता है कि यह मूल्य 127 से बड़ा है और 2048 से कम है, इसलिए इसे 2 बाइट्स में एन्कोड किया जाना चाहिए:
110x xxxx 10xx xxxx <-- UTF-8 encoding for Unicode 128-2047
***0 0011 **10 1001 <-- 0xe9
1100 0011 1010 1001 <-- 'é' after UTF-8 encoding
C 3 A 9
UTF-8 एन्कोडिंग के बाद 0xe9 यूनिकोड कोड 0xc3a9 हो जाता है। जो वास्तव में टर्मिनल को कैसे प्राप्त होता है। यदि आपका टर्मिनल लैटिन -1 (गैर-यूनिकोड विरासत एन्कोडिंग में से एक) का उपयोग करते हुए तार को डीकोड करने के लिए सेट है, तो आपको Ã © दिखाई देगा, क्योंकि ऐसा सिर्फ इसलिए होता है कि लैटिन -1 में 0xc3 अंक से Ã और 0x99 तक ©।