5

コマンドラインで実行した場合とEmacselisp関数の一部として実行した場合のPythonスクリプトの動作の違いを理解しようとしています。

スクリプトは次のようになります(私はPython 2.7.1 BTWを使用しています):

import json; t = {"Foo":"ザ"}; print json.dumps(t).decode("unicode_escape")

つまり、[一般的に]ユニコード文字を含むJSONセグメントを取得し、それをユニコードエスケープバージョンにダンプストリングしてから、デコードしてユニコード表現に戻します。コマンドラインで実行すると、これのダンプ部分は次を返します。

'{"Foo": "\\u30b6"}'

印刷すると次のようになります。

'{"Foo": "\u30b6"}'

このデコード部分は次のようになります。

u'{"Foo": "\u30b6"}'

印刷すると次のようになります。

{"Foo": "ザ"}

つまり、少なくともユニコードをサポートするターミナル/コンソール(私のテストベッドではxterm)での構造の元の文字列表現。Windowsコンソールでは、Unicode文字に関して出力は正しくありませんが、スクリプトはエラーになりません。

Emacsでは、ダンプの変換はコマンドラインでの変換と同じですが(少なくとも印刷で確認する限り)、デコード部分は恐ろしいもので吹き飛ばされます。

UnicodeEncodeErrorのファイル""、1行目:'ascii'コーデックは位置9の文字u'\ u30b6'をエンコードできません:序数が範囲内にありません(128) `

スクリプトまたはEmacs(テストベッド23.1.1)のいずれかに関して、ここで基本的なものが欠けていると感じています。コマンドラインで発生するがEmacsでは発生しない正しいコーデック/ロケールを呼び出す印刷の自動魔法の部分はありますか?Emacs呼び出しのロケールを明示的に設定しようとしました(これはjsonロジックなしのスタブテストです):

"LC_ALL=\"en_US.UTF-8\" python -c 's = u\"Fooザ\"; print s'"

同じ例外が発生しますが、

"LC_ALL=\"en_US.UTF-8\" python -c 'import sys; enc=sys.stdout.encoding; print enc' "

エンコーディングが「なし」であることを示します。

以下を使用して変換を強制しようとした場合:

"LC_ALL=\"en_US.UTF-8\" python -c 's = u\"Fooザ\"; print s.encode(\"utf8\",\"replace\")'"

エラーはなくなりますが、結果は非Unicodeコンソールに表示される文字列の「文字化け」バージョンになります。

Fooa?¶

何か案は?

更新: unutbu --b / cのおかげで、ロケールIDが落ちます。コマンドは、utf8-encodeで明示的に装飾する必要があります(Unicode文字列を直接操作するための回答を参照してください)。私の場合、dumps/decodeシーケンスから必要なものを取得しているので、必要な装飾を追加して、目的の結果を達成します。

import json; t = {"Foo":"ザ"}; print json.dumps(t).decode("unicode_escape").encode("utf8","replace")

これは、Emacsで必要なエスケープを含まない「生の」Pythonであることに注意してください。

この質問の元の部分を見て推測したかもしれませんが、私はこれをEmacsのJSONフォーマットロジックの一部として使用しています-この質問に対する私の答えを参照してください。

4

1 に答える 1

3

Python wikiページ、 「PrintFails」は言う

Python が出力の目的の文字セットを検出しない場合、sys.stdout.encoding を None に設定し、print は "ascii" コーデックを呼び出します。

Python が elisp 関数から実行されている場合、目的の文字セットを検出できないため、デフォルトで "ascii" になっているようです。そのため、Unicode を印刷しようとすると、暗黙のうちに Python が Unicode を ascii としてエンコードするようになり、これがエラーの原因です。


と置き換えるu\"Fooザ\"とうまくいくu\"Foo\\u30b6\"ようです:

(defun mytest ()
  (interactive)
  (shell-command-on-region (point)
         (point) "LC_ALL=\"en_US.UTF-8\" python -c 's = u\"Foo\\u30b6\"; print s.encode(\"utf8\",\"replace\")'" nil t))

C-x C-e M-x mytest

収量

Fooザ
于 2012-08-12T19:31:21.350 に答える