Python печатает символ Unicode

Я делаю карточную игру, но я столкнулся с тем, что кажется проблемой кодирования. Я пытаюсь распечатать такую ​​карточку:

def print(self):
    print("|-------|")
    print("| %s     |" % self.value)
    print("|       |")
    print("|   %s   |" % self.suit.encode("utf-8"))
    print("|       |")
    print("|    %s  |" % self.value)
    print("|-------|")

Это то, что я хочу:

|-------|
| 10    |
|       |
|   ♦   |
|       |
|    10 |
|-------|

... но это то, что я получаю:

|-------|
| 10    |
|       |
|   b'\xe2\x99\xa6'   |
|       |
|    10 |
|-------|

Я на Windows и Python 3, если это имеет значение.

Значение self.suit может быть любым из следующих:

spade = "♠"
heart = "♥"
diamond = "♦"
club = "♣"

Если я удаляю .encode( "utf-8" ), я получаю эту ошибку:

Traceback (последний последний вызов):

  File "main.py", line 79, in <module>
    start()
  File "main.py", line 52, in start
    play()
  File "main.py", line 64, in play
    card.print()
  File "main.py", line 36, in print
    print("|   \u2660   |")
  File "C:\Python34\lib\encodings\cp850.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2660' in position
4: character maps to <undefined>

Ответы

Ответ 1

Это использует тот факт, что страницы OEM-кода в консоли Windows печатают некоторые видимые символы для управляющих символов. Карточка подходит для cp437 и cp850 chr(3)-chr(6). Python 3 (до 3.6) не будет печатать символ Unicode для черного алмаза, но это то, что вы получаете за U + 0004:

>>> print('\N{BLACK DIAMOND SUIT}')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python33\lib\encodings\cp437.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2666' in position 0: character maps to <undefined>
>>> print(chr(4))
♦

Таким образом:

#!python3
#coding: utf8
class Card:
    def __init__(self,value,suit):
        self.value = value
        self.suit = suit    # 1,2,3,4 = ♥♦♣♠

    def print(self):
        print("┌───────┐")
        print("| {:<2}    |".format(self.value))
        print("|       |")
        print("|   {}   |".format(chr(self.suit+2)))
        print("|       |")
        print("|    {:>2} |".format(self.value))
        print("└───────┘") 

Вывод:

>>> x=Card('K',4)
>>> x.print()
┌───────┐
| K     |
|       |
|   ♠   |
|       |
|     K |
└───────┘
>>> x=Card(10,3)
>>> x.print()
┌───────┐
| 10    |
|       |
|   ♣   |
|       |
|    10 |
└───────┘

Обновление Python 3.6

Python 3.6 использует API-интерфейсы Windows Unicode для печати, поэтому нет необходимости в трюке управляющего символа, и можно использовать строки нового формата:

#!python3.6
#coding: utf8
class Card:
    def __init__(self,value,suit):
        self.value = value
        self.suit = '♥♦♣♠'[suit-1] # 1,2,3,4 = ♥♦♣♠

    def print(self):
        print('┌───────┐')
        print(f'| {self.value:<2}    |')
        print('|       |')
        print(f'|   {self.suit}   |')
        print('|       |')
        print(f'|    {self.value:>2} |')
        print('└───────┘') 

Вывод:

>>> x=Card('10',3)
>>> x.print()
┌───────┐
| 10    |
|       |
|   ♣   |
|       |
|    10 |
└───────┘