বিট এবং বিভিন্ন উত্তর থেকে টুকরো ধন্যবাদ, আমি মনে করি আমরা একটি ব্যাখ্যা সেলাই করতে পারেন।
একটি ইউনিকোড স্ট্রিং মুদ্রণ করার চেষ্টা করে, আপনি 'xe9', পাইথন স্পষ্টতই sys.stdout.encoding- এ সঞ্চিত এনকোডিং স্কিমটি ব্যবহার করে সেই স্ট্রিংটিকে এনকোড করার চেষ্টা করুন। পাইথন বাস্তবে যে পরিবেশটি শুরু হয়েছিল সেখান থেকে এই সেটিংটি তুলেছে। যদি এটি পরিবেশ থেকে কোনও সঠিক এনকোডিং খুঁজে না পায় তবে কেবলমাত্র এটি তার ডিফল্ট , এএসসিআইআইতে ফিরে আসে ।
উদাহরণস্বরূপ, আমি ব্যাশ শেল ব্যবহার করি যা ইউটিএফ -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)
পাইথন থেকে বেরিয়ে আসুন এবং ব্যাশ শেলটি বাতিল করুন।
পাইথনের আউটপুট স্ট্রিংয়ের পরে কী ঘটে তা আমরা এখন পর্যবেক্ষণ করব। এর জন্য আমরা প্রথমে গ্রাফিক টার্মিনালের মধ্যে ব্যাশ শেলটি শুরু করব (আমি জিনোম টার্মিনালটি ব্যবহার করি) এবং আমরা টার্মিনালটি ISO-8859-1 ওরফে ল্যাটিন -1 দিয়ে আউটপুট ডিকোড করতে সেট করব (গ্রাফিক টার্মিনালগুলিতে সাধারণত অক্ষর সেট করার বিকল্প থাকে) তাদের ড্রপডাউন মেনুগুলির একটিতে এনকোডিং )। মনে রাখবেন যে এটি আসল শেল পরিবেশের এনকোডিংটি পরিবর্তন করে না , এটি কেবলমাত্র টার্মিনাল দ্বারা প্রদত্ত আউটপুটকে ডিকোড করার উপায়টি পরিবর্তন করবে, যেমনটি ওয়েব ব্রাউজারের মতো করে। আপনি শেল এর পরিবেশ থেকে স্বাধীনভাবে টার্মিনালের এনকোডিং পরিবর্তন করতে পারেন। আসুন তাহলে শেল থেকে পাইথন শুরু করি এবং যাচাই করুন যে sys.stdout.encoding শেল পরিবেশের এনকোডিং (আমার জন্য ইউটিএফ -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) পাইথন বাইনারি স্ট্রিংকে যেমন আউটপুট দেয়, টার্মিনাল এটি গ্রহণ করে এবং ল্যাটিন -১ অক্ষর মানচিত্রের সাথে এর মানটি মিলানোর চেষ্টা করে। লাতিন -১ এ, 0xe9 বা 233 "é" অক্ষর দেয় এবং তাই টার্মিনালটি প্রদর্শিত হয়।
(2) পাইথন প্রচেষ্টা পরোক্ষভাবে যাই হোক না কেন স্কীম দিয়ে ইউনিকোড স্ট্রিং এনকোড বর্তমানে এই দৃষ্টান্ত এটা এর "হল UTF-8", sys.stdout.encoding মধ্যে সেট করা হয়। ইউটিএফ -8 এনকোডিংয়ের পরে, বাইনারি স্ট্রিংটি '\ xc3 \ xa9' (পরে ব্যাখ্যা দেখুন) explanation টার্মিনালটি এর মতো স্ট্রিমটি গ্রহণ করে এবং ল্যাটিন -1 ব্যবহার করে 0xc3a9 ডিকোড করার চেষ্টা করে, তবে ল্যাটিন -1 0 থেকে 255 পর্যন্ত যায় এবং তাই, একবারে কেবল 1 বাইট স্ট্রিমকে ডিকোড করে। 0xc3a9 2 বাইট দীর্ঘ, লাতিন -1 ডিকোডার তাই 0xc3 (195) এবং 0xa9 (169) হিসাবে এটি ব্যাখ্যা করে এবং এটি 2 টি অক্ষর দেয়: Ã এবং © ©
(3) পাইথন ল্যাটিন -1 স্কিমের সাথে ইউনিকোড কোড পয়েন্ট ইউ '\ xe9' (233) এনকোড করে। লাতিন -১ কোড পয়েন্টের সীমাটি 0-255 হয় এবং সেই পরিসরের মধ্যে ইউনিকোডের মতো একই চরিত্রের দিকে নির্দেশ করে। সুতরাং, ল্যাটিন -১ এ এনকোড করা হলে সেই পরিসরে ইউনিকোড কোড পয়েন্টগুলি একই মান অর্জন করবে। সুতরাং ল্যাটিন -1 এ এনকোড করা আপনার '\ xe9' (233) বাইনারি স্ট্রিং '\ xe9' উপার্জন করবে। টার্মিনালটি সেই মানটি অর্জন করে এবং লাতিন -১ অক্ষরের মানচিত্রে এটি মিলানোর চেষ্টা করে। কেস (1) এর মতো এটি "é" দেয় এবং এটি প্রদর্শিত হয়।
ড্রপডাউন মেনু থেকে এখন টার্মিনালের এনকোডিং সেটিংস ইউটিএফ -8 এ পরিবর্তন করুন (যেমন আপনি নিজের ওয়েব ব্রাউজারের এনকোডিং সেটিংস পরিবর্তন করতে পারেন)। পাইথন থামাতে বা শেলটি পুনরায় চালু করার দরকার নেই। টার্মিনালের এনকোডিংটি এখন পাইথনের সাথে মেলে। আবার মুদ্রণের চেষ্টা করুন:
>>> print '\xe9' # (4)
>>> print u'\xe9' # (5)
é
>>> print u'\xe9'.encode('latin-1') # (6)
>>>
(4) অজগর যেমন একটি বাইনারি স্ট্রিং আউটপুট দেয় । টার্মিনাল ইউটিএফ -8 দিয়ে সেই স্ট্রিমটি ডিকোড করার চেষ্টা করে। তবে ইউটিএফ -8 0xe9 মানটি বুঝতে পারে না (পরে ব্যাখ্যা দেখুন) এবং তাই এটি একটি ইউনিকোড কোড পয়েন্টে রূপান্তর করতে অক্ষম। কোনও কোড পয়েন্ট পাওয়া যায় নি, কোনও অক্ষর মুদ্রিত হয়নি।
(5) পাইথন করার জন্য প্রচেষ্টার সংখ্যা পরোক্ষভাবে যাই হোক না কেন sys.stdout.encoding এর সঙ্গে ইউনিকোড স্ট্রিং সঙ্কেতাক্ষরে লিখা। এখনও "ইউটিএফ -8"। ফলাফলযুক্ত বাইনারি স্ট্রিংটি '\ xc3 \ xa9'। টার্মিনালটি স্ট্রিমটি গ্রহণ করে এবং ইউটিএফ -8 ব্যবহার করে 0xc3a9 ডিকোড করার চেষ্টা করে। এটি ব্যাক কোড 0xe9 (233) দেয়, যা ইউনিকোড চরিত্রের মানচিত্রে "é" চিহ্নকে নির্দেশ করে। টার্মিনাল "é" প্রদর্শন করে।
()) পাইথন ল্যাটিন -১ এর সাথে ইউনিকোড স্ট্রিং এনকোড করে, এটি একই মান '\ xe9' সহ একটি বাইনারি স্ট্রিং দেয়। আবার, টার্মিনালের ক্ষেত্রে এটি বেশ প্রায় ক্ষেত্রে (4) এর মতো।
উপসংহার: - পাইথন অ-ইউনিকোড স্ট্রিংগুলিকে কাঁচা ডেটা হিসাবে আউটপুট করে, এর ডিফল্ট এনকোডিং বিবেচনা না করে। টার্মিনালটি কেবল তখনই প্রদর্শিত হয় যদি এর বর্তমান এনকোডিংটি ডেটার সাথে মেলে। - সিথ.স্টডআউট.এনকোডিং-এ উল্লিখিত স্কিমটি ব্যবহার করে পাইথন ইউনিকোড স্ট্রিংগুলি এনকোড করার পরে আউটপুট করে। - পাইথন শেল এর পরিবেশ থেকে সেটিংস পায়। - টার্মিনালটি তার নিজস্ব এনকোডিং সেটিংস অনুযায়ী আউটপুট প্রদর্শন করে। - টার্মিনালের এনকোডিংটি শেল থেকে স্বতন্ত্র।
ইউনিকোড, ইউটিএফ -8 এবং লাতিন -1 সম্পর্কিত আরও বিবরণ:
ইউনিকোড মূলত অক্ষরের একটি সারণি যেখানে কয়েকটি কী (কোড পয়েন্ট) প্রচলিতভাবে কিছু চিহ্নকে নির্দেশ করার জন্য নির্ধারিত করা হয়। উদাহরণস্বরূপ কনভেনশন দ্বারা সিদ্ধান্ত নেওয়া হয়েছে যে কী 0xe9 (233) হল 'é' প্রতীকটির দিকে নির্দেশ করা মান। এএসসিআইআই এবং ইউনিকোড 0 থেকে 127 পর্যন্ত একই কোড পয়েন্টগুলি ব্যবহার করে, যেমন ল্যাটিন -1 এবং ইউনিকোড 0 থেকে 255 পর্যন্ত। লাতিন -1 এবং ইউনিকোড, 0xe9 পয়েন্ট ল্যাটিন -1 এবং ইউনিকোডে 'é' এ দেখায়।
বৈদ্যুতিন ডিভাইসগুলির সাথে কাজ করার সময়, ইউনিকোড কোড পয়েন্টগুলির বৈদ্যুতিন উপস্থাপনের জন্য একটি কার্যকর উপায় প্রয়োজন। এটাই হচ্ছে এনকোডিং প্রকল্পগুলি। বিভিন্ন ইউনিকোড এনকোডিং স্কিম বিদ্যমান (utf7, UTF-8, UTF-16, UTF-32)। সবচেয়ে স্বজ্ঞাত এবং স্ট্রেইট ফরোয়ার্ড এনকোডিং পদ্ধতিটি ইউনিকোড মানচিত্রে একটি কোড পয়েন্টের মানটিকে তার বৈদ্যুতিন রূপের জন্য মান হিসাবে ব্যবহার করা হবে তবে ইউনিকোড বর্তমানে একটি মিলিয়নেরও বেশি কোড পয়েন্ট রয়েছে যার অর্থ তাদের কয়েকটিতে 3 বাইটের প্রয়োজন প্রকাশ করা হয়। পাঠ্যটির সাথে দক্ষতার সাথে কাজ করার জন্য, 1 থেকে 1 ম্যাপিংটি বরং ব্যবহারিক হবে, যেহেতু এটির প্রয়োজন হবে যে সমস্ত কোড পয়েন্ট তাদের যথাযথ প্রয়োজন বিবেচনা না করে, অক্ষরের প্রতি সর্বনিম্ন 3 বাইট সহ ঠিক একই পরিমাণে সঞ্চয় করা উচিত।
বেশিরভাগ এনকোডিং স্কিমগুলিতে স্থানের প্রয়োজনীয়তা সম্পর্কিত ত্রুটি রয়েছে, সর্বাধিক অর্থনৈতিক বিষয়গুলি সমস্ত ইউনিকোড কোড পয়েন্টগুলি আবরণ করে না, উদাহরণস্বরূপ ascii কেবল প্রথম 128 কভার করে, অন্যদিকে ল্যাটিন -1 প্রথম 256 টি অন্তর্ভুক্ত করে Others অপ্রয়োজনীয়, যেহেতু সাধারণ "সস্তা" অক্ষরের জন্য তাদের প্রয়োজনের তুলনায় আরও বেশি বাইট প্রয়োজন। উদাহরণস্বরূপ ইউটিএফ -১ 16, অ্যাস্কি রেঞ্জের অন্তর্ভুক্ত ('বি' যা 65, এখনও ইউটিএফ -16 এ 2 বাইট স্টোরেজ প্রয়োজন) সহ অক্ষর প্রতি সর্বনিম্ন 2 বাইট ব্যবহার করে। ইউটিএফ -32 আরও বর্জ্যযুক্ত কারণ এটি 4 টি বাইটে সমস্ত অক্ষর সংরক্ষণ করে।
ইউটিএফ -8 বুদ্ধিমান পরিমাণে বাইট স্পেস সহ কোড পয়েন্টগুলি সঞ্চয় করতে সক্ষম একটি স্কিম দিয়ে চতুরতার সাথে দ্বিধাটি সমাধান করেছে happens এর এনকোডিং কৌশলের অংশ হিসাবে, ইউটিএফ -8 ফ্ল্যাগ বিটের সাথে কোড পয়েন্ট দেয় যা তাদের স্থানের প্রয়োজনীয়তা এবং তাদের সীমানা নির্দেশ করে (সম্ভবত: ডিকোডারগুলিতে)।
ইউএসএফ -8 এসকিআই পরিসরে ইউনিকোড কোড পয়েন্টগুলির এনকোডিং (0-127):
0xxx xxxx (in binary)
- এক্সগুলি এনকোডিংয়ের সময় কোড পয়েন্ট "সঞ্চয়" করার জন্য প্রকৃত স্থানটি সংরক্ষিত দেখায়
- শীর্ষস্থানীয় 0 হল একটি পতাকা যা ইউটিএফ -8 ডিকোডারকে নির্দেশ করে যে এই কোড পয়েন্টটিতে কেবল 1 বাইট প্রয়োজন হবে require
- এনকোডিংয়ের পরে, ইউটিএফ -8 নির্দিষ্ট রেঞ্জের কোড পয়েন্টের মান পরিবর্তন করে না (অর্থাত্ ইউটিএফ -8 এ 65 এনকোডেডও 65)। ইউনিকোড এবং এএসসিআইআই একই পরিসরে সামঞ্জস্যপূর্ণ বিবেচনা করে, এটি ঘটনাক্রমে ইউটিএফ -8 এবং এএসসিআইআইকেও এই ব্যাপ্তিতে সামঞ্জস্য করে।
যেমন 'বি' এর জন্য ইউনিকোড কোড পয়েন্টটি '0x42' বা বাইনারিতে 0100 0010 (যেমন আমরা বলেছি, এটি ASCII তে একই)। ইউটিএফ -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
যখন ইউটিএফ -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
ইউটিএফ -8 এনকোডিংয়ের পরে 0xe9 ইউনিকোড কোড পয়েন্ট 0xc3a9 হয়ে যায়। টার্মিনালটি এটি ঠিক কীভাবে গ্রহণ করবে। যদি আপনার টার্মিনালটি ল্যাটিন -১ (অ-ইউনিকোড উত্তরাধিকারের এনকোডিংগুলির মধ্যে একটি) ব্যবহার করে স্ট্রিংগুলি ডিকোড করতে সেট করা থাকে তবে আপনি Ã see দেখতে পাবেন, কারণ এটি ঠিক তাই ঘটে থাকে যে ল্যাটিন -1 পয়েন্টে 0xc3 থেকে Ã এবং 0xa9 থেকে © ©।