我目前正在开发一个项目,我需要在 powershell 中运行命令,并且部分输出不是英语(特别是希伯来语)。
例如(问题的简化版本),如果我想获取桌面的内容,并且有一个希伯来语文件名:
import subprocess
command = "powershell.exe ls ~/Desktop"
print (subprocess.run(command.split(), stdout=subprocess.PIPE).stdout.decode())
此代码将引发以下错误(或具有不同字节值的类似错误):
UnicodeDecodeError: 'utf8' codec can't decode byte 0x96 in position 19: invalid start byte
尝试在另一台计算机上运行它,这是输出:
?????
知道这是为什么吗?我该如何解决它?尝试了很多我在其他问题上看到的东西,但没有一个对我有用。
注意:以下 Python 3+ 解决方案原则上有效,但是:
使用下面的第一个解决方案,由于powershell.exe
Consolas
)会显示正确的输出。
pwsh.exe
选项 A:在执行脚本之前配置两者控制台和Python以使用UTF-8字符编码:
以使用UTF-8:
cmd.exe
,通过将活动 OEM 代码页切换到
65001
(UTF-8);请注意,此更改可能会影响会话中以后对控制台应用程序的所有调用,与 Python 无关,除非您恢复原始代码页(请参阅下面的选项 B):chcp 65001
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
配置 Python (v3+) 以使用 UTF-8 一致:[1]
PYTHONUTF8
设置为
1
,可能是持久; 临时:
cmd.exe
:
Set PYTHONUTF8=1
$env:PYTHONUTF8=1
-X utf8
传递给
python
解释器(注意:大小写): python -X utf8 somefile.py ...
Python UTF-8 模式,将成为 Python 3.15 中的默认模式。
注:
通过一次性配置步骤
import sys, ctypes, subprocess
# Switch Python's own encoding to UTF-8, if necessary
# This is the in-script equivalent of setting environment var.
# PYTHONUTF8 to 1 *before* calling the script.
sys.stdin.reconfigure(encoding='utf-8'); sys.stdout.reconfigure(encoding='utf-8'); sys.stderr.reconfigure(encoding='utf-8')
# Save the current console output code page and switch to 65001 (UTF-8)
previousCp = windll.kernel32.GetConsoleOutputCP()
windll.kernel32.SetConsoleOutputCP(65001)
# PowerShell now emits UTF-8-encoded output; decode it as such.
command = "powershell.exe ls ~/Desktop"
print(subprocess.run(command, stdout=subprocess.PIPE).stdout.decode())
# Restore the previous output console code page.
windll.kernel32.SetConsoleOutputCP(previousCp)
注:
由于仅设置了
windll.kernel32.SetConsoleCP(65001)
设置 input 控制台页面(这将再次暴露显示错误)。
on 传递该输出,则很重要:Python 3.x 默认使用活动的 ANSI(!) 代码页进行编码 非控制台输出,这意味着希伯来语字符无法在非控制台输出中表示(例如,重定向到文件时),并导致脚本中断。