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 


Source: https://habr.com/ru/post/J148137/


All Articles