python:打开cmd.exe执行命令后出现中文内容缺失/乱码
代码打开cmd.exe接口self.__processsubprocess.Popen(cmd.exe,stdinsubprocess.PIPE,stdoutsubprocess.PIPE,stderrsubprocess.STDOUT)self.__cmd_pidself.__process.pid logger.debug(fnew console started)读取内容outself.__process.stdout.read(1)ifnotout:continueoutout.decode(gbk,errorsignore)ifisinstance(out,bytes)elseout发送命令self.__process.stdin.write(f{s}{line_break}.encode(gbk))ifflush:self.__process.stdin.flush()问题1没读到中文字符现象发送命令ping www.baidu.com -S 172.16.10.11时cmd.exe实际显示正在 Ping www.a.shifen.com[153.3.238.28]从172.16.10.11具有32字节的数据:PING传输失败。常见故障。 PING传输失败。常见故障。 PING传输失败。常见故障。 PING传输失败。常见故障。153.3.238.28的 Ping 统计信息:数据包:已发送4已接收0丢失4(100%丢失)但实际读取到的内容为ping www.baidu.com-S172.16.13.99Ping www.a.shifen.com[124.237.178.35]172.16.13.9932:PING PING PING PING124.237.178.35Ping::404(100%)问题定位outoutput_stream.stdout.read(1)# 每次只读取 1 个字节outout.decode(gbk,errorsignore)# 用 GBK 解码无法解码就丢弃这里存在 两个问题1. 逐字节解码导致多字节字符丢失中文字符在 GBK/UTF-8 中都是 多字节编码GBK 占2字节UTF-8 占3字节。read(1) 每次只读 1个字节对于双字节的 “传” 字第一次读到前导字节 \xd5单独用 GBK decode errors“ignore” → 被判定为不完整序列 → 丢弃第二次读到尾随字节 \xfd单独 decode → 又丢弃结果就是所有中文全部被静默丢弃只剩下单字节的英文字母、数字和符号。2. 编码假设可能不匹配代码硬编码使用 GBK 解码但实际 adb shell 或现代 Windows 控制台输出的可能是 UTF-8。即便把 read(1) 改成批量读取GBK 解码 UTF-8 字节流也同样会乱码或丢字。验证你可以在 Python 里验证这个现象传.encode(gbk)b\xb4\xabb\xb4.decode(gbk,errorsignore)# 只取第一个字节# 直接丢了b\xab.decode(gbk,errorsignore)# 只取第二个字节# 又丢了修复方案使用 增量解码器 配合 UTF-8 编码兼容性更好importcodecs# 在 __continuous_read_from_cmd_output 方法里decodercodecs.getincrementaldecoder(utf-8)(errorsreplace)whileself.__thd_stop_event.is_set():# ...outoutput_stream.stdout.read(1)ifnotout:continue# 增量解码自动处理多字节字符边界chardecoder.decode(out)ifchar:# 只有凑齐完整字符后才返回...补充为什么直接看 cmd 窗口是正常的Windows 控制台cmd 窗口有自己的字符缓冲和编码处理机制能正确组装多字节字符。而 WinExpect 是自己从 stdout 管道逐字节读、逐字节解码没有做任何字节缓冲所以把多字节中文拆碎了。问题2按问题1中的解决思路结局后打印结果中又出现乱码这说明编码选择不对——实际字节流是编码A而我用编码B去解码导致中文映射到了错误的 Unicode 码位上。先在cme.exe窗口中输入chcp看打印结果我的为936活动代码页:936修复方案importcodecs# 在 __continuous_read_from_cmd_output 方法里decodercodecs.getincrementaldecoder(gbk)(errorsreplace)whileself.__thd_stop_event.is_set():# ...outoutput_stream.stdout.read(1)ifnotout:continue# 增量解码自动处理多字节字符边界chardecoder.decode(out)ifchar:# 只有凑齐完整字符后才返回...总结chcp936 → 用 GBKchcp65001 → 才用 UTF-8无论用哪种编码必须配合增量解码器或至少按行读取不能逐字节 decode