Powershell/Windows中的CompletedProcess.stdout在Python中的编码是什么?

bkkx9g8r  于 2022-12-23  发布在  Shell
关注(0)|答案(2)|浏览(121)

我从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运行这个脚本,它在法语的Windows 10 21 H2上运行Powershell。所以我希望编码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"

0x 88应为ê,0x 82应为è

q1qsirdb

q1qsirdb1#

Windows上的 * 控制台 * 应用程序通常使用控制台的活动代码页对其输出进行编码,默认情况下,该代码页是系统的传统 OEM 代码页(例如,美国英语系统上的CP437),而不是 GUI 应用程序使用的传统 ANSI 代码页(例如,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代码页的常用单字节代码页不使用BOM,any 字节值也是有效字符。
  • 这最终使得任何试图检测未知编码是什么的尝试都是“猜测"--尽管猜测正确的概率可以通过复杂的语言分析来提高。
  • 我不知道chardet.detect()使用的是什么方法,但在本例中它猜错了;可以从confidence值的存在来推断它是“猜测的”。

0x88应为ê,并且0x82应为è
这实际上适用于CP 437,而不适用于Windows-1252,如以下PowerShell代码所示:

PS> [System.Text.Encoding]::GetEncoding(437).GetString([byte[]] (0x88, 0x82))

êé
watbbzwu

watbbzwu2#

如果任何一个人在这里降落,小工作剪切的基础上mklement0的答案。

import locale
import ctypes
import subprocess

oemCP = ctypes.windll.kernel32.GetConsoleOutputCP()
print(f'{locale.getpreferredencoding()=}')

encoding = "cp" + str(oemCP)
print(f"{encoding=}")

p = subprocess.run('dir c:\\',
                   shell=True,
                   stdout=subprocess.PIPE,
                   universal_newlines=True,
                   encoding=encoding,
                   stderr=subprocess.STDOUT)

print(p.stdout)

相关问题