如何正确运行UTF-16BE编码的Python脚本?输出异常排查
我来帮你拆解这个问题,核心在于Python解析源文件编码的逻辑,咱们一步步说:
为什么终端无输出?
你的test.py是UTF-16BE编码,但从print "test utf-16"的语法来看,你用的是Python 2,它解析源文件的规则是这样的:
- 首先会扫描文件开头的几行,寻找
# coding=xxx格式的编码声明,以此确定源文件编码; - 如果找不到有效的编码声明,Python 2默认会用ASCII来解析整个文件。
但你的文件是UTF-16BE编码,每个字符占2字节,比如开头的# coding=UTF-16BE这句话,在字节流里是0x00 0x23 0x00 0x20 0x00 0x63 ...这样的双字节序列。Python按默认的ASCII扫描时,会把大量的0x00空字节当成无效内容,根本识别不到# coding=这个ASCII格式的声明。
结果就是Python用ASCII去解析整个UTF-16BE文件,所有内容都变成了乱码,Python无法正确解析代码逻辑,要么直接静默报错(因为编码错误导致解析失败,错误信息可能因为编码不匹配没显示在终端),要么代码根本没被执行到print语句,自然就没有输出。
怎么解决?
有几个可行的方案,按推荐程度排序:
方案1:将文件转成UTF-8编码(最省心)
UTF-8是当前绝大多数环境的默认编码,不管是Python、bash终端还是编辑器都能很好支持。你可以用iconv命令转换:
iconv -f UTF-16BE -t UTF-8 test.py > test_utf8.py
然后执行python test_utf8.py,就能正常输出了。
方案2:给UTF-16BE文件添加BOM
Python可以自动识别带BOM的UTF-16文件(不管BE还是LE)。你可以用工具给文件开头加上UTF-16BE的BOM(字节序列0xFE 0xFF),这样Python不需要编码声明就能正确识别编码。比如用xxd和cat组合:
# 先生成包含BOM的文件 echo -n -e "\xFE\xFF" > bom.txt # 合并BOM和原文件 cat bom.txt test.py > test_with_bom.py
然后执行python test_with_bom.py,就能正常执行了。
方案3:确保编码声明被Python正确识别
如果你一定要保留UTF-16BE编码且不加BOM,那需要让Python能正确扫描到编码声明,但因为UTF-16BE是双字节编码,Python按ASCII扫描时找不到# coding=,这个方案操作复杂,不如前两个实用,不推荐。
和bash的默认编码有关吗?
关系不大。bash的默认编码(由LANG、LC_CTYPE等环境变量控制)主要影响终端的输出显示,比如如果Python正确执行了print,但输出的字符串是UTF-16BE编码,终端可能显示乱码,但不会完全没输出。
你这个问题的根源是Python无法正确解析源文件的编码,导致代码没被执行,和bash的编码设置没有直接关系。
内容的提问来源于stack exchange,提问作者VeryLazyBoy

