UCS2またはUCS4? -pyodbcおよびMSSQLでutf16データを操作

問題



UTF-16エンコーディング(UCS2)でMSSQL Server 2005データベースを操作するには、Pythonで記述されたスクリプトを使用します。 このスクリプトは、次の一連のツールを使用してデータベースを操作します。



そして、ここで問題が発生しました:データベース(nvarchar、ntextフィールド)から文字列データを受信すると、Unicodeが正しく処理されません。

結局のところ、私がインストールしたpythonはUCS4 unicodeでビルドされました。 PythonアセンブリでUnicode型を取得する方法は、stackoverflowに関するこの質問で詳しく説明されています。 つまり、ターミナルで次の行を実行すると:
python -c "import sys;print 'UCS4' if sys.maxunicode > 65536 else 'UCS2'"
      
      



次に、Python用のユニコードアセンブリバージョンを取得します。私の場合はUCS4でした。 これがそれ自体を引き付けるもの:

  1. 対応するデータベース関数を付録Wで呼び出すunixODBC(たとえば、 SQLExecDirectW() )が結果を取得します。 テキストの1文字が2バイトを占める(UCS2)
  2. pyodbcはODBCドライバーから結果を受け取り、その結果をUnicode変数に保存します
  3. したがって、pyodbcによると、結果の1文字は4バイト(UCS4)です。 これが結果の保存方法です。 ODBCドライバーから取得します。


ドライバーは、文字が2バイトを占めるデータを返し、pyodbcはこのデータを再実行して、文字が4バイトを占めるようにします。 変換が行われた場合はすべて問題ありませんが、データは単純にバイト配列としてUnicode型の変数に保存されますが、これは不快な結果をもたらします:結果文字には、基本的にODBCドライバーによって返された結果の2文字が含まれます。



ひどい結果ではありませんでしたが、私は結果を決定し、独立して変換し、シンボルで分割しました:

 def odbcUCS4toUCS2(ustr): u = u"" for i in range(0, len(ustr)): u32 = ord(ustr[i]) u16 = [(u32 & 0xFFFF0000) >> 16, (u32 & 0x0000FFFF)] u += unichr(u16[1]) u += unichr(u16[0]) return u
      
      





これは十分ではありませんでした。 別の不快な結果がありました:結果の文字の長さが奇数の場合、結果の最後の文字が切り捨てられます。 つまり 文字列'this word'は、スクリプトで'this words'として受信されます 。 変換ではこの問題を解決できませんでした。Unicodeストレージが正しくないため、結果の最後の2バイトは実際にはありません。 次に、UCS2 Unicodeサポートを使用してPythonを再構築することにしました。



解決策



オプション--enable-unicode = ucs2で指定することを忘れないでください。 新しいpythonをビルドするときは、zlib1g-devパッケージをインストールすることを忘れないでください。そうしないと、pipを使用したパッケージのインストールに問題が生じる可能性があります。

virtualenvをインストールして構成します。

 $ sudo apt-get install virtualenv $ virtualenv ~/ucs2env -p [   ucs2 ]
      
      





さて、エイリアスを追加します。
 echo "alias ucs2env='source ~/ucs2env/bin/activate'">>~/.bashrc
      
      





まあ、それだけです。 これで、データベースに保存されているのと同じ方法でデータが取得されます。

 $ ucs2env (ucs2env)$ python -c "import sys;print 'UCS4' if sys.maxunicode > 65536 else 'UCS2'" UCS2
      
      






All Articles