ऐसी एन्कोडिंग समस्याओं की पूरी कुंजी यह समझना है कि सिद्धांत में "स्ट्रिंग" की दो अलग-अलग अवधारणाएं हैं : (1) वर्णों की स्ट्रिंग , और (2) स्ट्रिंग / बाइट्स की सरणी।। 256 से अधिक वर्णों (ASCII, Latin-1, Windows-1252, Mac OS Roman,…) के साथ एन्कोडिंग की ऐतिहासिक सर्वव्यापकता के कारण इस अंतर को लंबे समय से नजरअंदाज किया गया है: ये एनकोडिंग आम पात्रों का एक सेट मैप करते हैं। 0 और 255 (यानी बाइट्स) के बीच की संख्या; वेब के आगमन से पहले फाइलों के अपेक्षाकृत सीमित आदान-प्रदान ने असंगत एनकोडिंग की इस स्थिति को सहनीय बना दिया, क्योंकि अधिकांश कार्यक्रम इस तथ्य को अनदेखा कर सकते थे कि जब तक वे एक ही ऑपरेटिंग सिस्टम पर बने रहे पाठ का उत्पादन करते हुए कई एन्कोडिंग थे: ऐसे कार्यक्रम बस पाठ को बाइट्स के रूप में समझें (ऑपरेटिंग सिस्टम द्वारा उपयोग किए गए एन्कोडिंग के माध्यम से)। निम्नलिखित दो बिंदुओं के आधार पर सही, आधुनिक दृश्य इन दो स्ट्रिंग अवधारणाओं को ठीक से अलग करता है:
वर्ण ज्यादातर कंप्यूटर से असंबंधित होते हैं : कोई उन्हें चाक बोर्ड पर आकर्षित कर सकता है, आदि, उदाहरण के लिए باي中ون, ث 蟒 और rel। मशीनों के लिए "वर्ण" में "ड्राइंग निर्देश" भी शामिल हैं जैसे उदाहरण के लिए रिक्त स्थान, गाड़ी वापसी, लेखन दिशा निर्धारित करने के लिए निर्देश (अरबी, आदि के लिए), लहजे, आदि। एक बहुत बड़ी चरित्र सूची यूनिकोड मानक में शामिल है ; इसमें अधिकांश ज्ञात चरित्र शामिल हैं।
दूसरी ओर, कंप्यूटर को किसी तरह से सार वर्णों का प्रतिनिधित्व करने की आवश्यकता होती है: इसके लिए, वे बाइट्स (0 और 255 के बीच की संख्या) की सरणियों का उपयोग करते हैं , क्योंकि उनकी स्मृति बाइट विखंडन में आती है। वर्णों को बाइट में परिवर्तित करने वाली आवश्यक प्रक्रिया को एन्कोडिंग कहा जाता है । इस प्रकार, वर्णों का प्रतिनिधित्व करने के लिए कंप्यूटर को एन्कोडिंग की आवश्यकता होती है । आपके कंप्यूटर पर मौजूद कोई भी पाठ एन्कोडेड है (जब तक कि यह प्रदर्शित न हो जाए), चाहे वह किसी टर्मिनल को भेजा जाए (जो एक विशिष्ट तरीके से एन्कोड किए गए वर्णों की अपेक्षा करता है), या किसी फ़ाइल में सहेजा गया। प्रदर्शित होने या ठीक से "समझने" के लिए (द्वारा, पायथन दुभाषिया), बाइट्स की धाराओं को पात्रों में डिकोड किया जाता है। कुछ एनकोडिंग(UTF-8, UTF-16,…) को यूनिकोड द्वारा उसके पात्रों की सूची के लिए परिभाषित किया गया है (यूनिकोड इस प्रकार इन पात्रों के लिए वर्ण और एनकोडिंग दोनों की एक सूची को परिभाषित करता है - अभी भी ऐसे स्थान हैं जहां कोई व्यक्ति "यूनिकोड एन्कोडिंग" को एक के रूप में देखता है सर्वव्यापी यूटीएफ -8 को संदर्भित करने का तरीका, लेकिन यह गलत शब्दावली है, क्योंकि यूनिकोड कई एनकोडिंग प्रदान करता है )।
सारांश में, कंप्यूटर को बाइट्स के साथ वर्णों का आंतरिक रूप से प्रतिनिधित्व करने की आवश्यकता होती है , और वे दो ऑपरेशनों के माध्यम से ऐसा करते हैं:
एन्कोडिंग : वर्ण → बाइट्स
डिकोडिंग : बाइट्स → अक्षर
कुछ एन्कोडिंग सभी वर्णों (जैसे, ASCII) को एन्कोड नहीं कर सकते, जबकि (कुछ) यूनिकोड एनकोडिंग आपको सभी यूनिकोड वर्णों को एनकोड करने की अनुमति देते हैं। एन्कोडिंग भी आवश्यक रूप से अद्वितीय नहीं है , क्योंकि कुछ वर्णों को सीधे या संयोजन के रूप में दर्शाया जा सकता है (उदाहरण के लिए एक आधार चरित्र और लहजे का)।
ध्यान दें कि नई लाइन की अवधारणा जटिलता की एक परत जोड़ती है , क्योंकि इसे विभिन्न (नियंत्रण) वर्णों द्वारा दर्शाया जा सकता है जो ऑपरेटिंग सिस्टम पर निर्भर करते हैं (यह पायथन की यूनिवर्सल न्यूलाइन फाइल रीडिंग मोड का कारण है )।
अब, जिसे मैंने ऊपर "वर्ण" कहा है, जिसे यूनिकोड " उपयोगकर्ता-कथित चरित्र " कहता है । यूनिकोड सूची में विभिन्न अनुक्रमितों पर पाए जाने वाले चरित्र भागों (आधार चरित्र, लहजे, ...) के संयोजन से एक उपयोगकर्ता-कथित चरित्र को कभी-कभी यूनिकोड में दर्शाया जा सकता है , जिसे " कोड पॉइंट " कहा जाता है - इस तरह के कोड बिंदुओं को एक साथ जोड़ा जा सकता है एक "ग्रैपहेम क्लस्टर"। यूनिकोड इस प्रकार स्ट्रिंग की एक तीसरी अवधारणा की ओर जाता है, जो यूनिकोड कोड बिंदुओं के अनुक्रम से बना है, जो बाइट और चरित्र स्ट्रिंग्स के बीच बैठता है, और जो बाद के करीब है। मैं उन्हें " यूनिकोड स्ट्रिंग्स " (जैसे पायथन 2 में) कहूंगा ।
जबकि पायथन (उपयोगकर्ता-कथित) वर्णों के तार मुद्रित कर सकते हैं , पायथन गैर-बाइट तार अनिवार्य रूप से यूनिकोड कोड बिंदुओं के अनुक्रम हैं , उपयोगकर्ता-कथित वर्णों के नहीं। कोड बिंदु मान पायथन \uऔर \Uयूनिकोड स्ट्रिंग सिंटैक्स में उपयोग किए गए हैं । उन्हें एक चरित्र के एन्कोडिंग के साथ भ्रमित नहीं होना चाहिए (और इसके साथ कोई संबंध नहीं रखना है: यूनिकोड कोड बिंदुओं को विभिन्न तरीकों से एन्कोड किया जा सकता है)।
इसका एक महत्वपूर्ण परिणाम है: एक पायथन (यूनिकोड) स्ट्रिंग की लंबाई कोड अंकों की संख्या है, जो हमेशा उपयोगकर्ता-कथित पात्रों की संख्या नहीं होती है : इस प्रकार s = "\u1100\u1161\u11a8"; print(s, "len", len(s))(पायथन 3) एकल उपयोगकर्ता-माना (कोरियाई) होने के 각 len 3बावजूद देता है sचरित्र (क्योंकि यह 3 कोड बिंदुओं के साथ दर्शाया गया है - भले ही यह print("\uac01")शो के रूप में नहीं है )। हालांकि, कई व्यावहारिक परिस्थितियों में, एक स्ट्रिंग की लंबाई उपयोगकर्ता-कथित पात्रों की संख्या है, क्योंकि कई पात्रों को आमतौर पर एक एकल यूनिकोड कोड बिंदु के रूप में पायथन द्वारा संग्रहीत किया जाता है।
में अजगर 2 , यूनिकोड तार कहा जाता है ... "यूनिकोड तार" ( unicodeप्रकार, शाब्दिक रूप u"…") है, जबकि बाइट सरणियों "तार" (हैं strप्रकार, जहां बाइट्स की सरणी उदाहरण के लिए स्ट्रिंग शाब्दिक साथ निर्माण किया जा सकता "…")। में अजगर 3 , यूनिकोड तार बस "तार" (कहा जाता है strप्रकार, शाब्दिक रूप "…",), जबकि बाइट सरणियों "बाइट" (हैं bytesप्रकार, शाब्दिक रूप b"…")। परिणामस्वरूप, "🐍"[0]पायथन 2 ( '\xf0', बाइट) और पायथन 3 ( "🐍", पहला और एकमात्र चरित्र) में कुछ अलग परिणाम देता है ।
इन कुछ प्रमुख बिंदुओं के साथ, आपको संबंधित एन्कोडिंग से संबंधित प्रश्नों को समझने में सक्षम होना चाहिए!
आम तौर पर, जब आप प्रिंट u"…" एक टर्मिनल के लिए , आप नहीं कचरा मिलना चाहिए: अजगर अपने टर्मिनल की एन्कोडिंग को जानता है। वास्तव में, आप जाँच सकते हैं कि टर्मिनल क्या एन्कोडिंग करता है:
% python
Python 2.7.6 (default, Nov 15 2013, 15:20:37)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.stdout.encoding
UTF-8
यदि आपके इनपुट वर्णों को टर्मिनल के एन्कोडिंग के साथ एन्कोड किया जा सकता है, तो पायथन ऐसा करेगा और शिकायत के बिना आपके टर्मिनल को संबंधित बाइट्स भेजेगा। टर्मिनल तब इनपुट बाइट्स को डिकोड करने के बाद वर्णों को प्रदर्शित करने के लिए अपनी पूरी कोशिश करेगा (सबसे खराब टर्मिनल फ़ॉन्ट में कुछ वर्ण नहीं हैं और इसके बजाय किसी प्रकार का रिक्त प्रिंट करेगा)।
यदि आपके इनपुट वर्णों को टर्मिनल के एन्कोडिंग के साथ एन्कोड नहीं किया जा सकता है, तो इसका मतलब है कि टर्मिनल इन पात्रों को प्रदर्शित करने के लिए कॉन्फ़िगर नहीं किया गया है। पायथन शिकायत करेगा ( UnicodeEncodeErrorचरित्र स्ट्रिंग के साथ पायथन में एक तरह से एन्कोड नहीं किया जा सकता है जो आपके टर्मिनल पर सूट करता है)। एकमात्र संभव समाधान एक टर्मिनल का उपयोग करना है जो वर्णों को प्रदर्शित कर सकता है (या तो टर्मिनल को कॉन्फ़िगर करके ताकि यह एक एन्कोडिंग को स्वीकार करता है जो आपके पात्रों का प्रतिनिधित्व कर सकता है, या एक अलग टर्मिनल प्रोग्राम का उपयोग करके)। यह महत्वपूर्ण है जब आप उन प्रोग्रामों को वितरित करते हैं जो विभिन्न वातावरणों में उपयोग किए जा सकते हैं: आपके द्वारा प्रिंट किए जाने वाले संदेश उपयोगकर्ता के टर्मिनल में प्रतिनिधित्व करने योग्य होने चाहिए। कभी-कभी इस प्रकार स्ट्रिंग्स से चिपकना सबसे अच्छा होता है जिसमें केवल एएससीआईआई अक्षर होते हैं।
हालाँकि, जब आप अपने प्रोग्राम के आउटपुट को रीडायरेक्ट या पाइप करते हैं , तो आमतौर पर यह जानना संभव नहीं होता है कि प्राप्त प्रोग्राम का इनपुट एन्कोडिंग क्या है, और उपरोक्त कोड कुछ डिफ़ॉल्ट एन्कोडिंग देता है: कोई नहीं (पायथन 2.7) या UTF-8 ( अजगर 3):
% python2.7 -c "import sys; print sys.stdout.encoding" | cat
None
% python3.4 -c "import sys; print(sys.stdout.encoding)" | cat
UTF-8
स्टड, stdout और stderr की एन्कोडिंग हालांकि जरूरत पड़ने पर पर्यावरण चर के माध्यम से सेट की जा सकती है PYTHONIOENCODING:
% PYTHONIOENCODING=UTF-8 python2.7 -c "import sys; print sys.stdout.encoding" | cat
UTF-8
यदि किसी टर्मिनल पर छपाई वह नहीं है जो आप उम्मीद करते हैं, तो आप UTF-8 एन्कोडिंग की जांच कर सकते हैं जिसे आपने मैन्युअल रूप से रखा है, सही है; उदाहरण के लिए, आपका पहला चरित्र ( \u001A) प्रिंट करने योग्य नहीं है, अगर मैं गलत नहीं हूँ ।
पर http://wiki.python.org/moin/PrintFails , आप अजगर 2.x के लिए निम्नलिखित की तरह एक समाधान है, पा सकते हैं:
import codecs
import locale
import sys
# Wrap sys.stdout into a StreamWriter to allow writing unicode.
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
uni = u"\u001A\u0BC3\u1451\U0001D10C"
print uni
पायथन 3 के लिए, आप StackOverflow पर पहले पूछे गए प्रश्नों में से एक की जाँच कर सकते हैं ।