因为Python默认用系统编码(Windows通常是cp936)输出,而字符串含UTF-8字节或非GBK字符(如emoji、中文引号、日文假名),sys.stdout写不进去就报UnicodeEncodeError。

为什么print()在Windows命令行里突然报UnicodeEncodeError?
因为Python默认用系统编码(Windows通常是cp936)输出,而你的字符串含UTF-8字节或非GBK字符(比如 emoji、中文引号、日文假名),sys.stdout写不进去就直接炸。这不是代码写错了,是环境和管道的编码对不上。
- 常见现象:
UnicodeEncodeError: 'gbk' codec can't encode character '\u201c' in position 0: illegal multibyte sequence - 别急着改源码——先确认终端是否支持UTF-8:
chcp 65001(Windows 10+有效) - 如果必须兼容旧终端,临时绕过:设置环境变量
PYTHONIOENCODING=utf-8,再运行脚本 - 更稳妥的做法:统一用
print(..., encoding='utf-8')?不行——print()没有encoding参数;得改sys.stdout重定向或用io.TextIOWrapper
读文件时指定encoding='utf-8'还不够,为什么还是乱码?
文件读取本身没问题,但后续处理(比如拼接、正则、写入新文件)可能隐式触发编码转换。尤其当字符串混入bytes对象,或调用str.encode()没指定编码时,Python会默认用sys.getdefaultencoding()(通常是utf-8),而写入目标设备却期望gbk,冲突就来了。
- 检查所有
open()调用:必须显式写encoding='utf-8',不能依赖默认值 - 避免
str + bytes拼接——会直接报TypeError,但有时被隐式转换掩盖 - 写文件时务必指定
encoding:open('out.txt', 'w', encoding='utf-8'),否则在Windows下默认用cp936 - 用
locale.getpreferredencoding()查当前系统编码,但别拿来当open()的encoding参数——它不可靠,尤其在IDE或CI环境中
requests返回的response.text为什么偶尔是乱码?
requests会根据HTTP响应头的Content-Type(如text/html; charset=utf-8)自动解码,但如果服务器没声明charset,或声明错误(比如标了gbk实际发的是UTF-8),response.text就会错。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 优先用
response.content.decode('utf-8')代替response.text,跳过自动猜测 - 若不确定编码,用
chardet.detect(response.content)['encoding']探测,但注意:小文本探测不准,慎用于生产 - 遇到
UnicodeDecodeError时,加errors='ignore'或errors='replace'临时兜底,但别长期用——掩盖问题 - POST提交数据时,确保
data是str而非bytes,否则requests不会自动加Content-Type: application/x-www-form-urlencoded; charset=utf-8
PyCharm / VS Code终端里正常,cmd里就崩,怎么统一?
IDE内置终端通常设为UTF-8,而Windows原生命令行默认是GBK。不是你的代码有问题,是执行环境分裂了。
立即学习“Python免费学习笔记(深入)”;
- 开发阶段:在脚本开头强制设置标准流编码:
import sys import io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
- 部署时:把
python.exe换成pythonw.exe?不行——那是GUI模式,没stdout;正确做法是封装成.bat并前置chcp 65001 >nul - 终极方案:不用
print()直接输出,改用logging模块,并配置handlers指定encoding='utf-8' - 注意:
sys.setdefaultencoding()已被禁用,不要试图调用它——这是早期Python 2的黑魔法,现在会静默失败
真正麻烦的不是单点修复,而是项目里不同模块各自假设编码,等数据流穿好几层才暴露问题。盯住open()、requests.get().text、print()这三处,其余地方基本是它们带出来的连锁反应。

















