5

我试图了解在命令行上运行与作为 Emacs elisp 函数的一部分运行时的一些 Python 脚本行为的区别。

脚本看起来像这样(我使用的是 Python 2.7.1 BTW):

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

也就是说,[通常] 获取一个包含 unicode 字符的 JSON 段,将其转储到它的 unicode 转义版本,然后将其解码回它的 unicode 表示。在命令行上运行时,转储部分返回:

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

打印时看起来像:

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

这个的解码部分看起来像:

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

打印时看起来像:

{"Foo": "ザ"}

即,结构的原始字符串表示,至少在支持unicode的终端/控制台中(在我的测试平台中,一个xterm)。在 Windows 控制台中,关于 unicode 字符的输出不正确,但脚本不会出错。

在 Emacs 中,转储转换与命令行上的转换相同(至少就打印确认而言),但解码部分令人恐惧:

文件“”,第 1 行,在 UnicodeEncodeError:'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 语言环境标识下降,该命令需要用 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”编解码器。

似乎当从 elisp 函数运行 python 时,它无法检测到所需的字符集,因此它默认为“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 回答