2012-02-14 9 views
3

unichr(0x10000)は、--enable-unicode=ucs4なしでcpythonをコンパイルするとValueErrorで失敗します。PythonでUnicode文字列を補完するコードポイント

任意のユニコードスカラー値またはコードポイントを、プログラムが実行されているPythonインタープリタの種類に関係なく動作するunicode文字列に変換する言語組み込み関数またはコアライブラリ関数はありますか?

+0

私はこれができないことを確信しています。それは、他の誰かのPythonが任意のUnicodeデータを実行するのを信頼できない理由の1つです。しかし、これはv3.3のリリースで修正されているようです。抽象的なUnicodeが必要な場合は、次のリリースを待つか、より堅牢なプラットフォームを使用する必要があります。 – tchrist

+0

@tchrist、ありがとう。うん。私はPython3.xを学ぶ必要があります。混乱の原因はほとんどありません。 –

+0

私は(ほとんど)@tchristには同意できません。下の私の答えを見てください。 –

答えて

8

はい、ここに行く:理解する

>>> unichr(0xd800)+unichr(0xdc00) 
u'\U00010000' 

重要なポイントは、unichr()はPythonインタプリタの文字列エンコーディングで単一のコード単位の整数に変換することです。それはUCS2 [0のいずれであってもよい - The Python Standard Library documentation for 2.7.3, 2. Built-in Functions, on unichr()

リターンに、 Unicodeのコード整数iが1文字のUnicode文字列を読み込み....引数の有効範囲は、Pythonが設定されたかによって決まります。 .0xFFFF]またはUCS4 [0..0x10FFFF]。それ以外の場合はValueErrorが生成されます。

「1文字」に重点を置いて、それは"one code unit" in Unicode termsを意味します。

私はあなたがPython 2.xを使用していると仮定しています。 Python 3.xインタプリタには、組み込みのunichr()関数はありません。代わりThe Python Standard Library documentation for 3.3.0, 2. Built-in Functions, on chr()

リターンに、UnicodeのコードポイントI ....引数の有効範囲は0から1,114,111(ベース16から0x10FFFF)によるものである整数である文字を表す文字列を読み出します。

戻り値は、コード単位が1つの文字列ではなく、不特定の長さの文字列になりました。したがって、Python 3.xでは、chr(0x10000)は期待どおりに動作します。これは、任意のUnicodeスカラ値またはコードポイントを、プログラムが実行されているPythonインタプリタの種類に関係なく動作するunicode文字列に変換します。

しかし、Python 2.xに戻る。 unichr()を使用してPython 2.x unicodeオブジェクトを作成し、0xFFFFより大きいUnicodeスカラー値を使用している場合は、Pythonインタプリタのunicodeオブジェクトの実装を認識するようにコードをコミットしています。

あなたはスカラー値でunichr()をしようとする機能で、この意識を分離することができ、ValueErrorをキャッチし、対応するUTF-16サロゲートペアを再試行します:

def unichr_supplemental(scalar): 
    try: 
     return unichr(scalar) 
    except ValueError: 
     return unichr(0xd800 + ((scalar-0x10000)//0x400)) \ 
       +unichr(0xdc00 + ((scalar-0x10000)% 0x400)) 

>>> unichr_supplemental(0x41),len(unichr_supplemental(0x41)) 
(u'A', 1) 
>>> unichr_supplemental(0x10000), len(unichr_supplemental(0x10000)) 
(u'\U00010000', 2) 

しかし、あなただけにそれが簡単に見つけるかもしれませんコード

>>> '\x00\x00\x00\x41'.decode('utf-32be'), \ 
... len('\x00\x00\x00\x41'.decode('utf-32be')) 
(u'A', 1) 
>>> '\x00\x01\x00\x00'.decode('utf-32be'), \ 
... len('\x00\x01\x00\x00'.decode('utf-32be')) 
(u'\U00010000', 2) 

:あなたのスカラーは4バイトのUTF-32、UTF-32バイトstringの値に変換し、unicode文字列にこのバイトstringをデコード上記のコードはUnicode文字列のためのUTF-16エンコーディングでPython 2.6.7でテストされました。私はUnicode文字列のためのUTF-32エンコーディングでPython 2.xインタープリターでそれをテストしませんでした。しかし、Python 2.xインタプリタでUnicode文字列を実装しても、それは変更されません。

+0

良い答え。最近のPythonのリリースでは、「ワイドビルド」の問題全体が取り除かれていることに注意してください。以前のリリースを実行している場合は、確かに "ワイドビルド"を使用する必要があります。 – tchrist

+0

あなたは2.xについて正しいです。仕様へのポインタとそれらの違いの説明に感謝します。 –

関連する問題