来自 Powershell/Windows in Python 的 CompletedProcess.stdout 的编码是什么?
What is the encoding of CompletedProcess.stdout coming from Powershell/Windows in Python?
我从 Python 和 subprocess.run()
:
开始的 ping 请求中得到了这个输出
>>> process.stdout
b"\r\nEnvoi d'une requ\x88te 'ping' sur www.google.fr [142.250.179.195] avec 32 octets de donn\x82es\xff:\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=39 ms TTL=110\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=46 ms TTL=110\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=37 ms TTL=110\r\n\r\nStatistiques Ping pour 142.250.179.195:\r\n Paquets\xff: envoy\x82s = 3, re\x87us = 3, perdus = 0 (perte 0%),\r\nDur\x82e approximative des boucles en millisecondes :\r\n Minimum = 37ms, Maximum = 46ms, Moyenne = 40ms\r\n"
我 运行 这个脚本来自 Pycharm 运行s Powershell on a Windows 10 21H2 法语。所以我希望编码 Windows-1252。这也是chardet的猜测:
>>> chardet.detect(process.stdout)
{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}
但是用 Windows-1252 解码看起来不太正确:
>>> process.stdout.decode("windows-1252")
"\r\nEnvoi d'une requˆte 'ping' sur www.google.fr [142.250.179.195] avec 32 octets de donn‚esÿ:\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=39 ms TTL=110\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=46 ms TTL=110\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=37 ms TTL=110\r\n\r\nStatistiques Ping pour 142.250.179.195:\r\n Paquetsÿ: envoy‚s = 3, re‡us = 3, perdus = 0 (perte 0%),\r\nDur‚e approximative des boucles en millisecondes :\r\n Minimum = 37ms, Maximum = 46ms, Moyenne = 40ms\r\n"
0x88 应该是 ê
而 0x82 应该是 è
Windows 上的控制台 应用程序通常使用控制台的活动代码页对其输出进行编码,默认情况下这是系统的遗留 OEM 代码页(例如,CP437
on US-English systems), not the legacy ANSI code page used by GUI applications (e.g, Windows-1252
):
您可以使用以下代码确定控制台的活动代码页并根据它进行解码:
import ctypes
import subprocess
# Get the console's active code page, as an integer.
oemCP = ctypes.windll.kernel32.GetConsoleOutputCP()
process = subprocess.run('ping.exe', capture_output=True)
# Decode based on the console's active code page.
print(process.stdout.decode("cp" + str(oemCP)))
有关 检测 编码的注释:
用作OEM和ANSI代码页的流行single-byte代码页不使用BOM,并且任何字节值也是有效字符。
这最终会尝试检测未知编码是什么猜测 - 尽管可以通过复杂的语言分析来提高猜测正确的概率。
我不知道chardet.detect()
用的是什么方法,但在这种情况下它猜错了;它 猜测 可以从 confidence
值的存在推断出来。
0x88
should be ê
and 0x82
should be è
这实际上适用于 CP437,不适用于 Windows-1252,如以下 PowerShell 代码所示:
PS> [System.Text.Encoding]::GetEncoding(437).GetString([byte[]] (0x88, 0x82))
êé
我从 Python 和 subprocess.run()
:
>>> process.stdout
b"\r\nEnvoi d'une requ\x88te 'ping' sur www.google.fr [142.250.179.195] avec 32 octets de donn\x82es\xff:\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=39 ms TTL=110\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=46 ms TTL=110\r\nR\x82ponse de 142.250.179.195\xff: octets=32 temps=37 ms TTL=110\r\n\r\nStatistiques Ping pour 142.250.179.195:\r\n Paquets\xff: envoy\x82s = 3, re\x87us = 3, perdus = 0 (perte 0%),\r\nDur\x82e approximative des boucles en millisecondes :\r\n Minimum = 37ms, Maximum = 46ms, Moyenne = 40ms\r\n"
我 运行 这个脚本来自 Pycharm 运行s Powershell on a Windows 10 21H2 法语。所以我希望编码 Windows-1252。这也是chardet的猜测:
>>> chardet.detect(process.stdout)
{'encoding': 'Windows-1252', 'confidence': 0.73, 'language': ''}
但是用 Windows-1252 解码看起来不太正确:
>>> process.stdout.decode("windows-1252")
"\r\nEnvoi d'une requˆte 'ping' sur www.google.fr [142.250.179.195] avec 32 octets de donn‚esÿ:\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=39 ms TTL=110\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=46 ms TTL=110\r\nR‚ponse de 142.250.179.195ÿ: octets=32 temps=37 ms TTL=110\r\n\r\nStatistiques Ping pour 142.250.179.195:\r\n Paquetsÿ: envoy‚s = 3, re‡us = 3, perdus = 0 (perte 0%),\r\nDur‚e approximative des boucles en millisecondes :\r\n Minimum = 37ms, Maximum = 46ms, Moyenne = 40ms\r\n"
0x88 应该是 ê
而 0x82 应该是 è
Windows 上的控制台 应用程序通常使用控制台的活动代码页对其输出进行编码,默认情况下这是系统的遗留 OEM 代码页(例如,CP437
on US-English systems), not the legacy ANSI code page used by GUI applications (e.g, Windows-1252
):
您可以使用以下代码确定控制台的活动代码页并根据它进行解码:
import ctypes
import subprocess
# Get the console's active code page, as an integer.
oemCP = ctypes.windll.kernel32.GetConsoleOutputCP()
process = subprocess.run('ping.exe', capture_output=True)
# Decode based on the console's active code page.
print(process.stdout.decode("cp" + str(oemCP)))
有关 检测 编码的注释:
用作OEM和ANSI代码页的流行single-byte代码页不使用BOM,并且任何字节值也是有效字符。
这最终会尝试检测未知编码是什么猜测 - 尽管可以通过复杂的语言分析来提高猜测正确的概率。
我不知道
chardet.detect()
用的是什么方法,但在这种情况下它猜错了;它 猜测 可以从confidence
值的存在推断出来。
0x88
should beê
and0x82
should beè
这实际上适用于 CP437,不适用于 Windows-1252,如以下 PowerShell 代码所示:
PS> [System.Text.Encoding]::GetEncoding(437).GetString([byte[]] (0x88, 0x82))
êé