Windows CMD与PowerShell中Python标准IO差异及CP1252字符问题问询
问题描述
我有一个两行的Python 3.10.7程序stdin.py:
import sys print(sys.stdin.read())
还有一个单行文本文件ansi.txt(CP1252编码),内容为:
‘I am well’ he said.
其中左右引号分别为0x91和0x92。
在Windows 10 CMD模式下,执行python stdin.py < ansi.txt可正常输出原内容;但在PowerShell中执行cat .\ansi.txt | python .\stdin.py时,引号会变为?。此外,Python直接读取该文件、PowerShell单独显示文件内容时,均可正常识别这些CP1252引号字符。
现问询:为何CMD与PowerShell搭配Python时行为不同?Python为何无法识别PowerShell管道传入的CP1252引号字符?
原因分析
1. CMD与PowerShell的管道/重定向编码逻辑差异
- CMD的重定向(
<)操作会直接传递文件的原始字节流给Python的标准输入,不做编码转换。Python在Windows下默认用系统ANSI编码(通常是CP1252,和文件编码匹配)解码输入字节,因此能正确解析引号。 - PowerShell的
cat是Get-Content的别名,它默认会先把CP1252编码的文件解码为Unicode字符串,再通过管道传递。而PowerShell管道的默认输出编码是UTF-16LE(Windows原生Unicode编码),但Python标准输入仍会用系统ANSI编码解码字节流,UTF-16LE字节用CP1252解码会出现无法识别的字符,最终显示为?。
2. 单独操作正常的原因
- Python直接读取文件时,默认调用系统ANSI编码(CP1252)解码,和文件编码一致,所以能正确解析。
- PowerShell单独显示文件时,
Get-Content用系统ANSI编码解码文件,控制台也用同编码输出,因此能正常显示引号。
解决办法
有三种可行的解决方式:
方式一:指定PowerShell输出编码为CP1252
执行命令时明确设置Get-Content的输出编码,让传递给Python的字节流和文件编码一致:Get-Content .\ansi.txt -Encoding CP1252 | python .\stdin.py方式二:让Python用UTF-16LE解码标准输入
修改Python脚本,指定和PowerShell管道匹配的编码:import sys print(sys.stdin.read(encoding='utf-16'))方式三:用CMD的
type命令替代cat
在PowerShell中调用CMD的type命令,它和CMD重定向逻辑一致,直接传递原始字节:type .\ansi.txt | python .\stdin.py
内容的提问来源于stack exchange,提问作者P. Wormer
相关产品推荐
相关产品推荐

