2015-11-27 5 views
2

Раньше я думал, что весь этот материал для кодирования довольно разобрался. Кажется, я ошибаюсь, потому что не могу объяснить, что здесь происходит.Какая кодировка символов используется в терминале IPython?

То, что я пытаюсь сделать, это использовать tabulate модуль для печати отформатированной таблицы с помощью

from tabulate import tabulate 
s = tabulate([[1,2],[3,4]], ["x","y"], tablefmt="fancy_grid") 
print(s) 

в IPython интерактивной консоли 3.5.0 под Windows, 10. Я ожидал, что результат будет

╒═════╤═════╕ 
│ x │ y │ 
╞═════╪═════╡ 
│ 1 │ 2 │ 
├─────┼─────┤ 
│ 3 │ 4 │ 
╘═════╧═════╛ 

, но вместо этого, я получил

UnicodeEncodeError: 'charmap' codec can't encode character '\u2552' in position 0: character maps to <undefined> 

Озадаченный, я попытался выяснить, где эта проблема была и смотрела на repr строки:

In [15]: s 
Out[15]: '╒═════╤═════╕\n│ x │ y │\n╞═════╪═════╡\n│ 1 │ 2 │\n├─────┼─────┤\n│ 3 │ 4 │\n╘═════╧═════╛' 

Хм, все персонажи могут быть отображены с помощью терминала (даже первый, который вызвал ошибку).

Просто проверка некоторые детали:

In [16]: sys.stdout.encoding 
Out[16]: 'cp850' 

In [17]: s.encode("cp850") 
[...] 
UnicodeEncodeError: 'charmap' codec can't encode character '\u2552' in position 0: character maps to <undefined> 

Так какая кодировка является терминал, использующий? Python говорит, что это cp850, и он говорит мне, что cp850 не имеет характера (which is true, это один из персонажей из cp437, которые должны были освободить место для акцентированных букв), но я могу видеть его в окне терминала !

Чтобы усложнить ситуацию, при использовании родной Python консоли вместо IPython, ошибка кажется более понятным:

>>> s 
'\u2552═══\u2564═══\u2555\n│ 1 │ 2 │\n├───┼───┤\n│ 3 │ 4 │\n\u2558═══\u2567═══\u255b' 
>>> sys.stdout.encoding 
'cp850' 
>>> print(s) 
Traceback (most recent call last): 
[...] 
UnicodeEncodeError: 'charmap' codec can't encode character '\u2552' in position 0: character maps to <undefined> 

Так, по крайней мере Python является последовательным, но то, что происходит с IPython?

+0

Если вы видите символы cp437, но Python говорит cp850, то Python является непоследовательным. Узнайте, на что фактически установлена ​​консоль (см., Например, [Какая кодировка/кодовая страница используется cmd.exe] (http://stackoverflow.com/questions/1259084/what-encoding-code-page-is-cmd- EXE-использование)). –

+0

@ThomasDickey: Я вижу * both * - строка, подобная '' ╒Í'', которая содержит символы, уникальные для обоих кодировок ('╒' только в' cp437' и 'Í' только в' cp850') отображается правильно ... –

+0

Я могу повторить этот результат в IPython.'Repr' в IPython должен быть таким же, как' repr', работающим прямо на Python, но это не так. –

ответ

1

IPython использует кодовую страницу OEM в интерактивном режиме, как и любой другой программы консоли Python:

In [1]: '\u2552' 
ERROR - failed to write data to stream: <_io.TextIOWrapper name='<stdout>' mode= 
'w' encoding='cp850'> 
Out[1]: 

In [2]: !chcp 
Active code page: 850 

Изменения результата, если установлен pyreadline (это позволяет цвета в консоли IPython между прочим):

In [1]: '\u2552' 
Out[1]: '╒' 

In [2]: import sys 

In [3]: sys.stdout.encoding 
Out[3]: 'cp850' 

In [4]: !chcp 
Active code page: 850 

Установлен pyreadline, IP-код sys.displayhook записывает результат в консольный объект readline, который использует WriteConsoleW() Windows Unicode API, который позволяет печатать даже un кодируемые на текущей кодовой странице. Символы Unicode (чтобы увидеть их, вам может потребоваться настроить шрифт (TrueType), такой как Lucida Console в консоли Windows).