IPython 终端使用哪种字符编码?
Which character encoding is the IPython terminal using?
我曾经认为我已经把整个编码的东西都弄清楚了。我似乎错了,因为我无法解释这里发生的事情。
我想做的是使用 tabulate
模块打印格式良好的 table 使用
from tabulate import tabulate
s = tabulate([[1,2],[3,4]], ["x","y"], tablefmt="fancy_grid")
print(s)
在IPython3.5.0的交互控制台下Windows10.我预计结果是
╒═════╤═════╕
│ 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
必须为重音字母腾出空间),但我可以 在终端中看到 它 window!
更复杂的是,当使用本机 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 是怎么回事?
IPython 在交互模式下像任何其他 Python 控制台程序一样使用 OEM 代码页:
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
后,IPython 的 sys.displayhook
将结果写入使用 WriteConsoleW()
Windows Unicode [=28] 的 readline 控制台对象=] 允许在当前代码页中打印甚至无法编码的 Unicode 字符(要查看它们,您可能需要在 Windows 控制台中配置 (TrueType) 字体,例如 Lucida Console)。
我曾经认为我已经把整个编码的东西都弄清楚了。我似乎错了,因为我无法解释这里发生的事情。
我想做的是使用 tabulate
模块打印格式良好的 table 使用
from tabulate import tabulate
s = tabulate([[1,2],[3,4]], ["x","y"], tablefmt="fancy_grid")
print(s)
在IPython3.5.0的交互控制台下Windows10.我预计结果是
╒═════╤═════╕
│ 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
必须为重音字母腾出空间),但我可以 在终端中看到 它 window!
更复杂的是,当使用本机 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 是怎么回事?
IPython 在交互模式下像任何其他 Python 控制台程序一样使用 OEM 代码页:
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
后,IPython 的 sys.displayhook
将结果写入使用 WriteConsoleW()
Windows Unicode [=28] 的 readline 控制台对象=] 允许在当前代码页中打印甚至无法编码的 Unicode 字符(要查看它们,您可能需要在 Windows 控制台中配置 (TrueType) 字体,例如 Lucida Console)。