Unicode在cp850(cp437)中打印不正确,扑克牌花色问题

3 投票
4 回答
7816 浏览
提问于 2025-04-16 07:23

总结一下:我该如何在不同系统上打印出扑克牌符号?

我觉得自己在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>

所以总的来说,我的控制台应用程序在不使用控制台,而是用IDLE的时候能正常工作。

当然,我可以通过chr函数自己生成这些符号:

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

但这样做看起来实在太傻了。而且我不想让程序只在Windows上运行,也不想有很多特殊情况(比如条件编译)。我希望代码能易于阅读。

我不在乎输出的是哪个字母,只要在任何设备上看起来都正确,无论是诺基亚手机、Windows还是Linux。Unicode应该可以做到,但在控制台上打印时却不正确

4 个回答

1

针对更新的问题的回答

既然你只是想在命令提示符(CMD)上打印UTF-8字符,那你可能会失望,因为CMD不支持UTF-8:
有没有可以显示Unicode字符的Windows命令行?

旧答案

你想做的事情不太清楚,我猜测你是想把编码过的 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', '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系统上是这样)。

2

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

import codecs

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

str = u'♠'

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

这样我就不需要每次发送内容到标准输出或错误输出时都去做一次encode('utf-8')的操作了。

1

使用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函数。

撰写回答