在Emacs中使用Python的Unicode转换问题

时间:2012-08-12 18:07:19

标签: python emacs unicode

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

脚本看起来像这样(我使用的是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行,in   UnicodeEncodeError:'ascii'编解码器无法对位置9中的字符u'\ u30b6'进行编码:序数不在范围内(128)`

我有一种感觉,我在这里缺少一些关于脚本或Emacs的基本内容(在我的testbed 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")

请注意,这是“原始”Python,没有Emacs所需的必要转义。

正如您在查看此问题的原始部分时所猜到的那样,我将其用作Emacs中某些JSON格式化逻辑的一部分 - 请参阅my answerthis question

1 个答案:

答案 0 :(得分:3)

Python wiki page, "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ザ