当控制台可能不处于 UTF-8 模式时,我有一些代码需要将某些非 ASCII 字符打印到控制台。
在 Linux 和 Mac 上,简单任何人都有责任使用非 UTF-8 终端来正确设置
LANG
和 LC_CTYPE
*。在 CPython ≥3.6 的 Windows 上,PSF 使用 PEP 528 处理此问题。
*如果你将来读到这篇文章(在 CPython ≥3.15 上),看起来会是 PYTHONIOENCODING
sys.stdout.encoding == 'utf-8'
启动,不管终端正在使用的实际代码页(并且没有“吵闹的用户”、Homebrew 维护者或 Linux 发行版管理员因没有设置良好的环境变量而被追究责任)在这种情况下。)。 我目前正在解决这个问题,只要将
sys.stdout.encoding
设置为
chcp
每当检测到“PyPy on Windows”时显示的内容即可解决此问题,但是当 PyPy 实现 PEP 528 时,这将失败:
import platform
import re
import subprocess
import sys
#import colorama
def fixit():
# implementation note: MUST be run before the first read from stdin.
# (stdout and sterr may be already written-to, albeit maybe corruptedly.)
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.reconfigure(encoding=sys.stdout._TTY_CODEPAGE)
时打电话给
sys.stdout.encoding != sys.stdout._TTY_CODEPAGE
是一件非常理智且正确的事情。 但这给我留下了一个问题:当 PEP 528 可能会或可能不会实施时,我到底如何才能在 Windows 上获得
sys.stdout._TTY_CODEPAGE
?
def has_pep528():
try:
import platform
import sys
if platform.python_implementation() == 'CPython' and tuple(sys.version_info) >= (3, 6):
return True
except:
pass
return False
当其他实现已知时,您可以添加额外的
if
语句。