当PEP 528可能未实现时,如何推导Windows控制台代码页?
Windows下Python终端非ASCII字符输出的编码适配问题及核心疑问
编码适配的现有方案差异
- Linux和Mac系统:若终端未使用UTF-8模式,用户需自行设置
LANG和LC_CTYPE环境变量;后续CPython ≥3.15版本将改用PYTHONIOENCODING来控制编码。 - Windows系统(CPython ≥3.6):通过PEP 528机制自动处理终端编码适配问题。
Windows下PyPy的特殊问题
Windows系统中的PyPy目前未实现上述编码适配逻辑:PyPy启动时会强制将sys.stdout.encoding设为utf-8,完全忽略终端实际使用的代码页,且该问题并非由用户、包维护者或系统管理员的环境变量设置错误导致。
当前的临时规避方案
我目前通过检测"Windows下的PyPy"场景,将标准流的编码设置为chcp命令返回的终端代码页来规避问题,但该方案会在PyPy实现PEP 528后失效:
import platform import re import subprocess import sys # import colorama def fixit(): # 实现说明:必须在首次读取stdin之前运行 # (stdout和stderr可能已被写入,只是内容可能损坏) if platform.system() == 'Windows': # colorama.just_fix_windows_console() if platform.python_implementation() == 'PyPy': if sys.pypy_version_info > (7, 3, 15): import warnings warnings.warn("Applying workaround for https://github.com/pypy/pypy/issues/2999") chcp_output = subprocess.check_output(['chcp.com'], encoding='ascii') cur_codepage = int(re.match(r'Active code page: (\d+)', chcp_output).group(1)) cur_encoding = WINDOWS_CODEPAGES[cur_codepage] for f in [sys.stdin, sys.stdout, sys.stderr]: if f.encoding != cur_encoding: f.reconfigure(encoding=cur_encoding) WINDOWS_CODEPAGES = { 437: 'ibm437', 850: 'ibm850', 1252: 'windows-1252', 28591: 'iso-8859-1', 28592: 'iso-8859-2', 28593: 'iso-8859-3', 65000: 'utf-7', 65001: 'utf-8' }
核心疑问
我认为当sys.stdout.encoding != sys.stdout._TTY_CODEPAGE时,调用sys.stdout.reconfigure(encoding=sys.stdout._TTY_CODEPAGE)是合理且正确的处理方式。但现在面临的问题是:在Windows系统中,无论PEP 528是否已实现,该如何获取sys.stdout._TTY_CODEPAGE?
内容的提问来源于stack exchange,提问作者JamesTheAwesomeDude
相关产品推荐
相关产品推荐

