我有一个 C++ 程序,它输出原始 UTF-8,并且在 Linux 上完美运行,但在 Windows shell 上,输出不太好。例如,“®”变成“┬«”,“©”变成“┬⌐”。 代码中还有一个 Python 部分,在打印到 shell 时似乎效果更好,所以我尝试测试一下 Python 输出。
PS C:\Users\user> python -c 'print("\N{GREEK CAPITAL LETTER DELTA}")' > test_file_python.txt
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u0394' in position 0: character maps to <undefined>
PS C:\Users\user> python -X utf8 -c 'print("\N{GREEK CAPITAL LETTER DELTA}")' > test_file_python.txt
PS C:\Users\user> cat test_file_python.txt
Δ
PS C:\Users\user> python -c 'print("\N{GREEK CAPITAL LETTER DELTA}")'
Δ
PS C:\Users\user> cat .\test_file_python_wsl.txt # Generated in WSL with the above commands
Δ
PS C:\Users\user> Format-Hex .\test_file_python.txt
Label: C:\Users\user\test_file_python.txt
Offset Bytes Ascii
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------ ----------------------------------------------- -----
0000000000000000 E2 95 AC C3 B6 0D 0A �ö��
PS C:\Users\user> Format-Hex .\test_file_python_wsl.txt
Label: C:\Users\user\test_file_python_wsl.txt
Offset Bytes Ascii
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------ ----------------------------------------------- -----
0000000000000000 CE 94 0A ��
我不明白 PowerShell 如何使用编码,Python 如何在写入 shell 时正确执行此操作,但在重定向时却不行,以及为什么在 WSL 中的 Linux Bash 中完美运行的东西在较新的跨平台 PowerShell 中却存在此类问题应该“正常工作”的核心。 这是多个问题,但可能有一个共同的答案。
编辑: 我忘记添加一些重要信息,我正在使用 PowerShell Core v7.3.6 和此编码设置:
PS C:\Users\user> $OutputEncoding
Preamble :
BodyName : utf-8
EncodingName : Unicode (UTF-8)
HeaderName : utf-8
WebName : utf-8
WindowsCodePage : 1200
IsBrowserDisplay : True
IsBrowserSave : True
IsMailNewsDisplay : True
IsMailNewsSave : True
IsSingleByte : False
EncoderFallback : System.Text.EncoderReplacementFallback
DecoderFallback : System.Text.DecoderReplacementFallback
IsReadOnly : True
CodePage : 65001
在 Windows 上,这个难题有两部分:
在与外部程序通信时,您必须指示 PowerShell(可能只是暂时)使用 UTF-8。
使用以下魔法咒语(请注意,
chcp 65001
,即您在cmd.exe
中所做的事情,是不是一个选项,因为.NET缓存存储在[Console]
中的编码):
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
您也必须指示 Python 使用 UTF-8 I/O(假设 Python v3.7+):
要么:将
-X utf8
(具体情况)传递给 python
可执行文件:
python -X utf8 -c 'print("\N{GREEK CAPITAL LETTER DELTA}")' > test_file_python.txt
或者:在调用 Python 之前,运行
$env:PYTHONUTF8=1
通过一次性配置步骤的另一种方法是将您的计算机切换为使用 UTF-8 系统范围,在这种情况下,无需执行上述步骤;然而,这会产生深远的影响,并且可能会破坏遗留脚本和应用程序 - 请参阅这个答案