ダミヌのためのナニコヌド

ロゎマヌク

私自身は「ダミヌ/鍋/鍋甚のポケモンゞュヌス」のような芋出しはあたり奜きではありたせんが、これは事実ず思われたす-基本的なこずに぀いお話したす。 「なぜ機胜しないのですか」 ただ怖い、および/たたはナニコヌドを理解しおいない堎合-私は猫を求めたす。





なんで



初心者の䞻な質問であり、印象的な゚ンコヌディングず、䞀芋耇雑なメカニズムPython 2.xなどに遭遇したす。 短い答えは、それが起こったためです:)



コヌディングは、知らないうちに、コンピュヌタヌのメモリヌれロ単䜍\数字で読みたすで数字、ブナ、その他すべおの文字を衚す方法ず呌ばれたす。 たずえば、スペヌスは0b100000バむナリ、3210進数、たたは0x2016進数ずしお衚されたす。



そのため、メモリが非垞に少なくなり、すべおのコンピュヌタヌに必芁なすべおの文字数字、小文字/倧文字のラテンアルファベット、䞀連の文字、いわゆる制埡文字-すべおの127の数字が誰かに䞎えられたしたを衚すのに十分な7ビットがありたした。 圓時の゚ンコヌディングは1぀のASCIIでした。 時間が経぀に぀れお、誰もが幞せで、誰も幞せではありたせんでした読む-「©」たたはネむティブの文字「u」を欠く人-残りの128文字を自由裁量で䜿甚したした。 そのため、 ISO-8859-1ずキリル文字の cp1251ずKOI8が登堎したした 。 それらに加えお、タむプ0b1 *******぀たり、128から255の文字\番号のバむトを解釈する問題が発生したした-たずえば、cp1251゚ンコヌディングの0b11011111はISOのネむティブ「I」であり、 8859-1はギリシャ語のドむツ語のEszett 月の出を告げるで「ß」です。 HTTPプロトコルの「Content-Encoding」などのヘッダヌ、電子メヌルメッセヌゞ、HTMLペヌゞが状況を少し保存したにもかかわらず、ネットワヌク通信ず異なるコンピュヌタヌ間のファむル共有だけが地獄の知識に倉わりたした。



その瞬間、明るい頭脳が集たり、新しい暙準であるUnicodeを提案したした。 これぱンコヌドではなく暙準です。Unicodeだけでは、文字がハヌドドラむブに保存される方法やネットワヌク経由で送信される方法は決定されたせん。 文字ず特定の数字の間の関係のみを定矩し、これらの数字がバむトに倉換される圢匏はUnicode゚ンコヌド UTF-8たたはUTF-16など によっお決定されたす。 珟圚、Unicode暙準には10䞇文字を少し超える文字がありたすが、UTF-16では100䞇を超える文字UTF-8などをサポヌトできたす。



このトピックに぀いお、壮倧なJoel Spolskyが絶察に最小のすべおの゜フトりェア開発者であり、ナニコヌドず文字セットに぀いお絶察に前向きに知っおおく必芁があるトピックを読むこずをお勧めしたす。



芁点を぀かもう



圓然、PythonでもUnicodeがサポヌトされおいたす。 しかし、残念ながら、Python 3でのみすべおの文字列がナニコヌドになり、初心者は次のような゚ラヌに぀いお自殺しなければなりたせん。



>>> with open('1.txt') as fh: s = fh.read() >>> print s  >>> parser_result = u'-' #   ,  ,     -  >>> parser_result + s
      
      



 Traceback (most recent call last): File "<pyshell#43>", line 1, in <module> parser_result + s UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 0: ordinal not in range(128)
      
      





たたは

 >>> str(parser_result)
      
      



 Traceback (most recent call last): File "<pyshell#52>", line 1, in <module> str(parser_result) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
      
      





それを理解したしょうが、順番に。



誰かがナニコヌドを䜿甚しおいるのはなぜですか


お気に入りのHTMLパヌサヌがUnicodeを返すのはなぜですか 通垞の文字列を返すようにしたしょう。そうすれば、すでにそこで察凊したす。 そう そうでもない。 Unicodeに存圚する各文字はおそらくいく぀かのシングルバむト゚ンコヌディングISO-8859-1、cp1251などはシングルバむトず呌ばれたす。文字を1バむトで正確に゚ンコヌドするためですが、文字列に文字がある堎合はどうでしょうか異なる゚ンコヌディングから 各文字に個別の゚ンコヌディングを割り圓おたすか いいえ、もちろん、Unicodeを䜿甚する必芁がありたす。



なぜ新しいタむプの「ナニコヌド」が必芁なのですか


だから、私たちは最も興味深いこずになりたした。 Python 2.xの文字列ずは䜕ですか これらは単なるバむトです。 䜕でもかたいたせん。 実際、次のようなものを曞くずき
 >>> x = 'abcd' >>> x 'abcd'
      
      



むンタヌプリタヌは、ラテンアルファベットの最初の4文字を含む倉数を䜜成したせんが、シヌケンスのみを䜜成したす
 ('a', 'b', 'c', 'd')
      
      



4バむトで、ラテン文字はこの特定のバむト倀を瀺すためにのみ䜿甚されたす。 ぀たり、ここでの「a」は「\ x61」を蚘述するための単なる同矩語であり、もう少しではありたせん。 䟋



 >>> '\x61' 'a' >>> struct.unpack('>4b', x) # 'x' -    signed/unsigned char- (97, 98, 99, 100) >>> struct.unpack('>2h', x) #   short- (24930, 25444) >>> struct.unpack('>l', x) #   long (1633837924,) >>> struct.unpack('>f', x) #  float (2.6100787562286154e+20,) >>> struct.unpack('>d', x * 2) #    double- (1.2926117739473244e+161,)
      
      





それだけです



そしお、質問ぞの回答-「ナニコヌド」が必芁な理由はより明癜です-バむトではなく文字で衚されるタむプが必芁です。



たあ、私はラむンが䜕であるか理解したした。 次に、PythonのUnicodeずは䜕ですか


「タむプナニコヌド」は、䞻にナニコヌドの抂念それらに関連付けられた文字ず数字のセットを実装する抜象化です。 「ナニコヌド」タむプのオブゞェクトは、もはやバむトのシヌケンスではなく、文字自䜓のシヌケンスであり、これらの文字がコンピュヌタヌのメモリにどのように効果的に保存されおいるかに぀いおはたったくわかりたせん。 必芁に応じお、これはバむト文字列よりも高い抜象化レベルですPython 3では、Python 2.6で䜿甚される通垞の文字列ず呌ばれたす。



Unicodeの䜿甚方法


Python 2.6でUnicode文字列を䜜成するには、3぀の少なくずも自然な方法がありたす。

最埌の2぀の䟋のasciiぱンコヌドずしお指定され、バむトを文字に倉換するために䜿甚されたす。 この倉換の段階は次のようになりたす。



 '\x61' ->  ascii ->   "a" -> u'\u0061' (unicode-point   )  '\xe0' ->  c1251 ->   "a" -> u'\u0430'
      
      







Unicode文字列から通垞を取埗する方法は ゚ンコヌドする



 >>> u'abc'.encode('ascii') 'abc'
      
      







コヌディングアルゎリズムは、圓然䞊蚘の逆です。



芚えおおいおください-混同しないでください-Unicode ==文字、文字列==バむト、およびバむト->意味のあるもの文字はデコヌドデコヌドであり、文字->バむトぱンコヌド゚ンコヌドです。



゚ンコヌドされおいない:(


蚘事の最初から䟋を芋おみたしょう。 文字列ずUnicode文字列の連結はどのように機胜したすか 単玔な文字列はUnicode文字列に倉換する必芁があり、むンタヌプリタヌぱンコヌドを知らないため、デフォルトの゚ンコヌドであるasciiを䜿甚したす。 この゚ンコヌドが文字列のデコヌドに倱敗するず、weい゚ラヌが発生したす。 この堎合、正しい゚ンコヌディングを䜿甚しお、文字列をUnicode文字列にキャストする必芁がありたす。



 >>> print type(parser_result), parser_result <type 'unicode'> - >>> s = '' >>> parser_result + s
      
      



 Traceback (most recent call last): File "<pyshell#67>", line 1, in <module> parser_result + s UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 0: ordinal not in range(128)
      
      



 >>> parser_result + s.decode('cp1251') u'\xe1\xe0\xe1\xe0-\xff\xe3\xe0\u043a\u043e\u0449\u0435\u0439' >>> print parser_result + s.decode('cp1251') - >>> print '&'.join((parser_result, s.decode('cp1251'))) -& #   :)
      
      







「UnicodeDecodeError」は通垞、正しい゚ンコヌディングを䜿甚しお文字列をUnicodeにデコヌドする必芁があるこずの蚌拠です。



珟圚、strおよびUnicode文字列を䜿甚しおいたす。 「str」およびナニコヌド文字列を䜿甚しないでください:)「str」でぱンコヌディングを指定する方法がないため、デフォルトの゚ンコヌディングが垞に䜿甚され、128文字を超えるず゚ラヌが発生したす。 「゚ンコヌド」メ゜ッドを䜿甚したす。



 >>> print type(s), s <type 'unicode'>  >>> str(s)
      
      



 Traceback (most recent call last): File "<pyshell#90>", line 1, in <module> str(s) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
      
      



 >>> s = s.encode('cp1251') >>> print type(s), s <type 'str'> 
      
      







「UnicodeEncodeError」は、Unicode文字列を通垞の文字列に倉換するずきに正しい゚ンコヌドを指定する必芁があるこずを瀺したすたたは「encode」メ゜ッドで2番目のパラメヌタヌ「ignore」\「replace」\「xmlcharrefreplace」を䜿甚したす。



もっず欲しい


さお、䞊蚘の䟋の銬堎やがを再び䜿甚したす。



 >>> parser_result = u'-' #1 >>> parser_result u'\xe1\xe0\xe1\xe0-\xff\xe3\xe0' #2 >>> print parser_result áàáà-ÿãà #3 >>> print parser_result.encode('latin1') #4 - >>> print parser_result.encode('latin1').decode('cp1251') #5 - >>> print unicode('-', 'cp1251') #6 -
      
      





この䟋は完党に単玔ではありたせんが、すべおたあ、たたはほずんどすべおがありたす。 ここで䜕が起こっおいたすか

  1. 入り口には䜕がありたすか IDLEがむンタヌプリタヌに枡すバむト。 出口で䜕が必芁ですか Unicode、぀たり文字。 バむトを文字に倉換するこずは残っおいたすが、゚ンコヌドが必芁ですよね どの゚ンコヌディングが䜿甚されたすか さらに調べたす。

  2. 重芁なポむントは次のずおりです。
     >>> '-' '\xe1\xe0\xe1\xe0-\xff\xe3\xe0' >>> u'\u00e1\u00e0\u00e1\u00e0-\u00ff\u00e3\u00e0' == u'\xe1\xe0\xe1\xe0-\xff\xe3\xe0' True
          
          



    ご芧のずおり、Pythonぱンコヌドの遞択を気にしたせん-バむトは単にUnicodeポむントに倉わりたす

     >>> ord('') 224 >>> ord(u'') 224
          
          



  3. ここにのみ問題がありたす-cp1251の224番目の文字むンタヌプリタヌが䜿甚する゚ンコヌドは、ナニコヌドの224ずたったく同じではありたせん。 このため、Unicode文字列を印刷しようずするずkrakozyabraが取埗されたす。

  4. 女性を助ける方法は 最初の256個のUnicode文字は、それぞれISO-8859-1 \ latin1゚ンコヌドず同じであるこずがわかりたす。それを䜿甚しおUnicode文字列を゚ンコヌドするず、入力したバむトを取埗したす気にするのは-Objects / unicodeobject.c 、関数「unicode_encode_ucs1」の定矩を探しおいたす

     >>> parser_result.encode('latin1') '\xe1\xe0\xe1\xe0-\xff\xe3\xe0'
          
          



  5. 女性をナニコヌドにする方法は 䜿甚する゚ンコヌドを指定する必芁がありたす。

     >>> parser_result.encode('latin1').decode('cp1251') u'\u0431\u0430\u0431\u0430-\u044f\u0433\u0430'
          
          



  6. ポむント5からのメ゜ッドは確かにそれほど暑くはありたせん。組み蟌みのunicodeを䜿甚する方がはるかに䟿利です。
実際、問題はコン゜ヌルでのみ発生するため、「u」リテラルのすべおがそれほど悪いわけではありたせん。 実際、゜ヌスファむルで非ASCII文字が䜿甚されおいる堎合、Pythonは "-*-coding-*-" PEP 0263 のようなヘッダヌの䜿甚を芁求し 、Unicode文字列は正しい゚ンコヌディングを䜿甚したす。



たずえば、キリル文字を衚すために「u」を䜿甚する方法もあり、゚ンコヌドたたは読み取り䞍胜なUnicodeポむント぀たり、「u '\ u1234'」を指定したせん。 この方法は完党に䟿利ではありたせんが、興味深いのはナニコヌド゚ンティティコヌドを䜿甚するこずです。



 >>> s = u'\N{CYRILLIC SMALL LETTER KA}\N{CYRILLIC SMALL LETTER O}\N{CYRILLIC SMALL LETTER SHCHA}\N{CYRILLIC SMALL LETTER IE}\N{CYRILLIC SMALL LETTER SHORT I}' >>> print s 
      
      







たあ、すべおがそうです。 䞻なヒントは、「゚ンコヌド」ず「デコヌド」を混同しないで、バむトず文字の違いを理解するこずです。



Python 3


経隓がないため、コヌドはありたせん。 目撃者は、すべおがそこでより簡単でより楜しいず䞻匵したす。 ここPython 2.xずそこPython 3.xの違い-尊敬ず尊敬の違いを実蚌するために、誰が猫を匕き受けたすか。



圹に立぀



゚ンコヌディングに぀いお話しおいるので、時々krakozyabraを克服するのに圹立぀リ゜ヌス-http://2cyr.com/decode/?lang=enをお勧めしたす



繰り返しになりたすが、Spolskyの蚘事ぞのリンク- すべおの゜フトりェア開発者が絶察的か぀積極的にUnicodeおよび文字セットに぀いお知っおおく必芁のある絶察最小倀です。



Unicode HOWTOは、Python 2.xのUnicodeの堎所、方法、理由に関する公匏ドキュメントです。



ご枅聎ありがずうございたした。 プラむベヌトでのコメントに感謝したす。



PSは、Spolsky- Absolute Minimumの翻蚳ぞのリンクを投げたした。これは、すべおの゜フトりェア開発者がUnicodeず文字セットに぀いお知っおいる必芁がありたす。



All Articles