Unicode在cp850(cp437)中打印不正确,扑克牌花色问题
总结一下:我该如何在不同系统上打印出扑克牌符号?
我觉得自己在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 个回答
针对更新的问题的回答
既然你只是想在命令提示符(CMD)上打印UTF-8字符,那你可能会失望,因为CMD不支持UTF-8:
有没有可以显示Unicode字符的Windows命令行?
旧答案
你想做的事情不太清楚,我猜测你是想把编码过的 UTF-8写入一个文件。
你遇到的问题有:
symbols = ('♠','♥', '♦','♣')
,虽然你的文件编码可能是UTF-8,但如果你不是在用Python 3,你的字符串默认不会是UTF-8,你需要在前面加一个小u
:
symbols = (u'♠', u'♥', u'♦', u'♣')
你的
str(arg)
会把unicode字符串转换回普通字符串,直接去掉它或者用unicode(arg)
来转换成unicode字符串。.decode()
这个名字可能会让人困惑,它是把字节解码成UTF-8,但你需要做的是编码UTF-8成字节,所以要用.encode()
你没有以二进制模式写入文件,应该用
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系统上是这样)。
每当我需要输出utf-8字符时,我会使用以下方法:
import codecs
out = codecs.getwriter('utf-8')(sys.stdout)
str = u'♠'
out.write("%s\n" % str)
这样我就不需要每次发送内容到标准输出或错误输出时都去做一次encode('utf-8')
的操作了。
使用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
函数。