【问题标题】:Unicode not printing correctly to cp850 (cp437), play card suitsUnicode 无法正确打印到 cp850 (cp437),扑克牌套装
【发布时间】:2010-11-20 14:38:03
【问题描述】:

总结一下:如何独立打印unicode系统来产生扑克牌符号?

我做错了什么,我认为自己在 Python 中相当流利,除了我似乎无法正确打印!

# coding: utf-8
from __future__ import print_function
from __future__ import unicode_literals
import sys

symbols = ('♥','♦','♠','♣')
# red suits to sdterr for IDLE
print(' '.join(symbols[:2]), file=sys.stderr)
print(' '.join(symbols[2:]))

sys.stdout.write(symbols) # also correct in IDLE
print(' '.join(symbols))

打印到控制台,这是控制台应用程序的主要问题,但失败得很惨:

J:\test>chcp
Aktiivinen koodisivu: 850


J:\test>symbol2
Traceback (most recent call last):
  File "J:\test\symbol2.py", line 9, in <module>
    print(''.join(symbols))
  File "J:\Python26\lib\encodings\cp850.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-3: character maps to <unde
fined>
J:\test>chcp 437
Aktiivinen koodisivu: 437

J:\test>d:\Python27\python.exe symbol2.py
Traceback (most recent call last):
  File "symbol2.py", line 6, in <module>
    print(' '.join(symbols))
  File "d:\Python27\lib\encodings\cp437.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode character u'\u2660' in position 0: character maps
o <undefined>

J:\test>

所以 summa summarum 我有控制台应用程序,只要您不使用控制台,而是 IDLE,它就可以工作。

我当然可以通过 chr 生成符号来自己生成符号:

# correct symbols for cp850
print(''.join(chr(n) for n in range(3,3+4)))

但这看起来很愚蠢。而且我不会让程序只在 Windows 上运行或有许多特殊情况(如条件编译)。我想要可读的代码。

我不介意它输出哪些字母,只要它看起来正确,无论是诺基亚手机、Windows 还是 Linux。 Unicode 应该可以,但无法正确打印到控制台

【问题讨论】:

  • Windows 控制台使用通常不可打印的字符打印卡片符号,特别是 print '\x03\x04\x05\x06'。 cp437(美国 Windows 控制台)和 cp850 本身不支持这些字符。请参阅本页表格末尾的注释:en.wikipedia.org/wiki/Code_page_850
  • 我知道,请参阅我修改后的帖子末尾的代码。 “C0 控制范围(0x00–0x1F 十六进制)被映射到图形字符。代码可以假定它们作为控件的原始功能(因为它们仍然这样做 - 键入“echo”、空格、control-G,然后 Enter 会导致 PC 扬声器发出哔声——即使在 Windows XP 的命令提示符下),但在显示中,例如在 MS-DOS 编辑等屏幕编辑器中,它们显示为图形。图形多种多样,如笑脸、卡片套装和音符。”他们在那里,为什么他们不打印为 unicode?​​span>

标签: python windows-xp cmd


【解决方案1】:

每当我需要输出 utf-8 字符时,我都会使用以下方法:

import codecs

out = codecs.getwriter('utf-8')(sys.stdout)

str = u'♠'

out.write("%s\n" % str)

每次需要将某些内容发送到 sdtout/stderr 时,这都会为我节省一个 encode('utf-8')

【讨论】:

  • 没有打印功能,sys.stdout 功能没有技巧。控制台错误消息包括我的帖子的结尾。
【解决方案2】:

使用 Unicode 字符串和 codecs 模块:

要么:

# coding: utf-8
from __future__ import print_function
import sys
import codecs

symbols = (u'♠',u'♥',u'♦',u'♣')

print(u' '.join(symbols))
print(*symbols)
with codecs.open('test.txt','w','utf-8') as testfile:
    print(*symbols, file=testfile)

或:

# coding: utf-8
from __future__ import print_function
from __future__ import unicode_literals
import sys
import codecs

symbols = ('♠','♥','♦','♣')

print(' '.join(symbols))
print(*symbols)
with codecs.open('test.txt','w','utf-8') as testfile:
    print(*symbols, file=testfile)

无需重新实现print

【讨论】:

  • +1 用于 unicode_literals 提示(顺便说一句,芬兰姓氏不错:)
【解决方案3】:

针对更新后的问题

既然您只想在 CMD 上打印出 UTF-8 字符,那么您很不走运,CMD 不支持 UTF-8:
Is there a Windows command shell that will display Unicode characters?

旧答案

您在这里尝试做什么并不完全清楚,我最好的选择是您想将 编码 UTF-8 写入文件。

你的问题是:

  1. symbols = ('♠','♥', '♦','♣') 虽然您的文件编码可能是 UTF-8,除非您使用 Python 3,否则默认情况下您的字符串不会是 UTF-8,您需要在它们前面加上一个小的 u:
    symbols = (u'♠', u'♥', u'♦', u'♣')

  2. 您的 str(arg) 将 unicode 字符串转换回普通字符串,只需将其省略或使用 unicode(arg) 转换为 unicode 字符串

  3. .decode() 的命名可能会造成混淆,这会将字节解码为 UTF-8,但您需要做的是编码 UTF-8成字节,所以使用.encode()

  4. 你不是以二进制模式写入文件,而不是open('test.txt', 'w'),你需要使用open('test.txt', 'wb')(注意wb)这将以二进制模式打开文件,这在Windows上很重要

如果我们把所有这些放在一起,我们会得到:

# -*- coding: utf-8 -*-
from __future__ import print_function
import sys

symbols = (u'♠',u'♥', u'♦',u'♣')

print(' '.join(symbols))
print('Failure!')

def print(*args,**kwargs):
    end = kwargs[end] if 'end' in kwargs else '\n'
    sep = kwargs[sep] if 'sep' in kwargs else ' '
    stdout = sys.stdout if 'file' not in kwargs else kwargs['file']
    stdout.write(sep.join(unicode(arg).encode('utf-8') for arg in args))
    stdout.write(end)

print(*symbols)
print('Success!')
with open('test.txt', 'wb') as testfile:
    print(*symbols, file=testfile)

这很高兴将字节 编码 UTF-8 写入文件(至少在我的 Ubuntu 机器上)。

【讨论】:

  • 编码不起作用,它只说:Traceback(最近一次调用最后一次):文件“J:\test\symbol.py”,第 20 行,在 print(*symbols) 文件中“J:\test\symbol.py”,第 14 行,打印 stdout.write(sep.join(str(arg).encode('utf8') for arg in args)) 文件“J:\test\symbol. py", line 14, in stdout.write(sep.join(str(arg).encode('utf8') for arg in args)) UnicodeEncodeError: 'ascii' codec can't encode character u'\u2660 ' 在位置 0:序数不在范围内(128)。解码工作,但只在 IDLE,而不是 CMD 控制台。
  • 你没有用unicode(arg)替换你的str(arg)调用,所以encode在非unicode字符串上会失败。
  • 是的,但文件的结果在 IDLE "♠♥ ♦ ♣" 中看起来很垃圾
  • 当然它看起来“垃圾”,因为现在你得到了 UTF8 字符串的字节表示。你期待什么?如果要取回符号,则需要从文件中读取,然后使用.decode('utf-8')
  • 另外你应该使用"wb"而不是"w"作为open的第二个参数以二进制模式写入文件,我很抱歉错过了。
【解决方案4】:

Windows 控制台中的 UTF-8 是一个漫长而痛苦的故事。

您可以阅读 issue 1602issue 6058 并找到一些有用的东西,或多或少,但它很脆弱。

让我总结一下:

  • Lib/encodings/aliases.py 中添加“cp65001”作为“utf8”的别名
  • 选择Lucida ConsoleConsolas 作为您的控制台字体
  • 运行chcp 65001
  • 运行python

【讨论】:

  • 我知道这些,但还没有设法让控制台仍然打印任何可理解的东西。也许过去有时会做同样的事情(我的默认值是从注册表 co cp1252 更改的。忘记在哪里。仍然没有扑克牌符号)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
  • 2015-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多