【问题标题】:Converting from ascii to utf-8 with Python使用 Python 从 ascii 转换为 utf-8
【发布时间】:2011-01-16 19:11:31
【问题描述】:

我有用 python 编写的 xmpp bot。它的插件之一能够执行操作系统命令并将输出发送给用户。据我所知,输出应该是类似 unicode 的,以便通过 xmpp 协议发送。所以我试着这样处理:

output = os.popen(cmd).read() 
if not isinstance(output, unicode):
   output = unicode(output,'utf-8','ignore')
bot.send(xmpp.Message(mess.getFrom(),output))

但是当俄罗斯符号出现在输出中时,它们并没有很好地转换。

sys.getdefaultencoding() 

说默认的命令提示符编码是'ascii',但是当我尝试这样做时

output.decode('ascii') 

在 python 控制台中我得到

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x92 in position 1: 
ordinal not in range(128)

操作系统:Win XP、Python 2.5.4 PS:对不起我的英语:(

【问题讨论】:

  • 你试过输出output = output.encode("utf-8')吗?
  • 更改为 output.decode('866') 帮助了我。但是 locale.getpreferredencoding(do_setlocale=True) 返回 cp1251。还有其他方法可以确定正确的编码吗?因为这个机器人也应该在 linux 下工作
  • Erm...ASCII 已经是 UTF-8 的完美子集了!根据定义,任何 ASCII 文本都是 UTF-8 文本。在这里是打算反过来还是 colriot 要求将其他编码转换为 UTF-8?

标签: python utf-8 ascii command-prompt


【解决方案1】:

sys.getdefaultencoding() 返回 python 的 默认编码 - 除非您更改了它,否则它是 ASCII。 ASCII 不支持俄语字符。

您需要手动或使用locale module 确定实际文本的编码方式。

通常是这样的:

import locale
encoding = locale.getpreferredencoding(do_setlocale=True)¶

【讨论】:

  • 在 Windows 上,即使 Python 在 MS-DOS 模拟命令提示符下运行,也会在 OP(俄语)设置中提供 cp1251; OP需要cp866
【解决方案2】:

Ascii 没有定义大于 127 0x7F 的字符值。也许您的意思是西里尔语代码页?是 866

http://en.wikipedia.org/wiki/Code_page

编辑:由于这个答案被标记为正确,大概 886 有效,但正如其他答案所指出的那样,886 不是唯一的俄语代码页。如果您使用的代码页与俄罗斯符号编码时使用的代码页不同,您将得到错误的结果。

【讨论】:

  • 请使用真实名称“KOI8-R”,而不是不透明的 Windows 名称“CP866”。
  • 但是a.decode('cp866')和a.decode('koi8-r')的结果不同
  • 如果有西里尔语代码页的可移植标识符,最好使用它。 Glenn,您有 KOI8-R 的参考资料吗?
  • 代码页 866 与 KOI8-R 完全不同,或者实际上与任何其他俄罗斯编码完全不同。作为 DOS 代码页,您通常不会再遇到它。参见en.wikipedia.org/wiki/Code_page_866 vs en.wikipedia.org/wiki/KOI8-R vs 更常见的en.wikipedia.org/wiki/Windows-1251
【解决方案3】:

你说 """sys.getdefaultencoding() 说默认命令提示符编码是 'ascii'"""

sys.getdefaultencoding 没有说明“命令提示符”编码。

在 Windows 上,sys.stdout.encoding 应该可以完成这项工作。在我的机器上,当 Python 在命令提示符窗口中运行时,它包含 cp850,在 IDLE 中包含 cp1252。你的应该分别包含cp866cp1251

更新你说在IDLE中你仍然需要cp866。请注意:

IDLE 2.6.4      
>>> import os
>>> os.popen('chcp').read()
'Active code page: 850\n'
>>>

因此,当您的应用启动时,请检查您是否在 Windows 上,如果是,请解析 os.popen('chcp').read() 的结果。 : 之前的文本可能与语言环境有关。 codepage = result.split()[-1] 可能已经足够“解析”了。在没有 Windows/MS-DOS 拆分个性的 Unix 上,sys.stdout.encoding 应该没问题。

【讨论】:

  • 谢谢!这正是我想要的
  • 还是不行。如何找出 os.popen(command).read() 默认编码?还是取决于命令
  • os.popen("command").read() 默认编码??没有这个概念。正在传输的数据的编码由 WRITER 选择(或强制);它与阅读器无关,阅读器需要知道或猜测编码或从可靠来源获取编码。你问来干什么?为什么 sys.stdout.encoding 不是你想要的?
  • 因为无论您是从命令提示符还是 IDLE 运行 python 都没有关系。 'cp866' 在这两种情况下都是正确的选择。
  • 谢谢。这种方法看起来很理想。但是当我尝试使用“ipconfig”命令测试机器人时......所以在这种情况下,“cp1251”是输出的真实编码。这是否意味着没有通用的方法来解决我的问题?
【解决方案4】:

在 Python 中,“cp855”、“cp866”、“cp1251”、“iso8859_5”、“koi8_r”是不同的俄语代码页。您需要使用正确的解码 popen 的输出。在 Windows 控制台中,“chcp”命令列出了控制台命令使用的代码页。这不一定是与 Windows 应用程序相同的代码页。在美国 Windows 上,“cp437”用于控制台,“cp1252”用于记事本等应用程序。

【讨论】:

    猜你喜欢
    • 2019-10-31
    • 2016-08-31
    • 2011-06-19
    • 2011-05-17
    • 2012-08-04
    • 2013-04-19
    • 2021-07-11
    • 2019-06-04
    • 2011-06-26
    相关资源
    最近更新 更多