Python子进程回显一个unicode文字

时间:2015-05-05 13:57:49

标签: python unicode subprocess unicode-literals

我之前已经问过这样的问题了。但我没有找到解决方案。

我想在子程序模块中使用我的python文件中定义的unicode文字。但我没有得到我需要的结果。例如以下代码

# -*- coding: utf-8 -*-
import sys
import codecs
import subprocess
cmd = ['echo', u'你好']
new_cmd = []
for c in cmd:
    if isinstance(c,unicode):
        c = c.encode('utf-8')
    new_cmd.append(c)
subprocess.call(new_cmd)

打印出来

你好

如果我将代码更改为

# -*- coding: utf-8 -*-
import sys
import codecs
import subprocess
cmd = ['echo', u'你好']
new_cmd = []
for c in cmd:
    if isinstance(c,unicode):
        c = c.encode(sys.getfilesystemencoding())
    new_cmd.append(c)
subprocess.call(new_cmd)

我得到以下

??

在这个阶段,我只能假设我反复犯了一个简单的错误。但我很难弄清楚它是什么。当通过python的子进程

调用时,如何获得echo以打印出以下内容
你好

编辑:

Python的版本是2.7。我在Windows 8上运行,但我希望解决方案与平台无关。

2 个答案:

答案 0 :(得分:2)

你的第一次尝试是最好的。

您实际上已经转换了UTF8中的2个unicode字符u'你好'(或u'\u4f60\u597d')所有提供b'\xe4\xbd\xa0\xe5\xa5\xbd'的内容。

您可以在IDLE中控制它,完全支持unicode以及b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')返回你好的位置。控制它的另一种方法是将脚本输出重定向到一个文件,并使用兼容UTF-8的编辑器打开它:再次,你会看到你想要的。

但问题是Windows控制台不支持完整的unicode。这取决于:

  • 安装的代码页 - 我不知道对于Windows 8,但以前的版本对unicode的支持很差,只能显示256个字符
  • 控制台中使用的字体 - 并非所有字体都包含所有字符的字形。

如果您知道包含字符字形的代码页(我没有),您可以尝试将其插入到chcp的控制台中,并明确地将您的unicode字符串编码为该字符串。但是在我的法国机器上,我不知道该怎么做......除非通过文本文件传递!

当你谈到ConEmu时,我试了一下......使用python 3.4它可以正常使用它!

chcp 65001
py -3
import subprocess
cmd = ['cmd', '/c', 'echo', u'\u4f60\u597d']
subprocess.call(cmd)

给出:

你好  
0

问题出在cmd.exe窗口!

答案 1 :(得分:1)

结论:注意字符编码(这里有三种不同的字符编码)。如果您需要可移植的Unicode支持(将参数作为Unicode传递,不对它们进行编码)或确保使用环境中的当前字符编码来表示数据(在Python 2上使用sys.getfilesystemencoding()进行编码),请使用Python 3在第二个代码示例中做。)

第一个代码示例不正确。效果与(在IDLE中运行 - py -3 -midlelib)相同:

>>> print(u'你好'.encode('utf-8').decode('mbcs')) #XXX DON'T DO IT!
你好

其中mbcs编解码器使用您的Windows ANSI code page(通常为cp1252字符编码 - 可能会有所不同,例如俄语Windows上的cp1251

Python 2使用CreateProcess宏来启动一个等同于CreateProcessA函数的子进程。 CreateProcessA将输入字节解释为使用Windows ANSI编码进行编码。它与Python源代码编码无关(在您的情况下为utf-8)。

如果使用错误的编码,预计会出现mojibake。

如果输入字符可以使用Windows代码页(例如cp1252表示(以启用从Unicode到字节的编码)以及echo使用Unicode API打印到Windows控制台,则第二个代码示例应该有效例如WriteConsoleW()(参见Python 3包win-unicode-console - 只要控制台中的字体支持,它就会启用print(u'你好') 你的chcp(“OEM”)字符)字符可以使用OEM代码页(由cmd.exe使用)来表示,例如cp437(运行chcp以查找您的代码)。 ??个问号表示无法使用您的控制台编码来表示你好

要支持任意Unicode参数(包括无法使用Windows(“ANSI”)或MS-DOS(OEM)代码页表示的字符),您需要CreateProcessW函数(由Python使用) 3)。请参阅Unicode filenames on Windows with Python & subprocess.Popen()