Python源文件一行字符过长造成的问题

网上看到的一个不错的帖子 记录下

新建一个Python文件输入以下内容:

1
2
3
e = {'合作社', '经济', '财税', '账', '旅行社', '维修', '押运', '管理咨询', '基业', '养生', '雕塑', '上海警', '首饰', '商行', '电脑', '人才网', '素食', '日用制品', '铝制品', '百货', '银行', '产业园', '商学院', '驾驶培训', '生活', '潜水服务', '电视台', '贸易', '副食', '铝业', '风投', '财经', '警察协会', '试验', '展会', '金融', '陶艺', '营业部', '眼镜', '物业', '飞手', '实验', '幼教', '超市', '植保机用户', '农服', '教育', '会展', '销售', '果业', '保险', '生态园', '企业管理', '印刷', '电力局', '传播', '贷', '拆迁', '装饰', '养老', '人寿', '生活馆', '财务', '餐饮', '咨询服务', '出品', '个体', '办公', '自由职业', '动漫', '中央', '商务', '老年人', '农资', '新华社', '博览会', '新华网', '珠宝', '航展', '工贸', '专利', '市政', '体验', '网吧', '水敏纸检测喷潵效果', '破产', '大申网', '促进会', '酒业', '烟草', '家政', '威海警', '自来水', '代理', '售货', '创意', '基金', '进出口', '融资', '银联', '制衣', '暂无', '成人', '影视', 'VC', '英烈', '风水', '营销', '摄影', '小公司', '广告', '国贸', '服饰', '招聘', '创业', '新闻', '兽药', '体育节', '母婴', '还没定', '农村信用合作社', '人力', '国际货运', '职业技能', '知识产权', '酒店', '理发', '中财', '经营', '体检', '证券', '宾馆', '科贸', '经销', '个人', '报社', '宇辰世纪', '旅游', '展览', '演出', '宇辰网', '出版社', '媒体', '认证咨询', '电子商务', '孵化', '化妆', '职业学院', '拍卖', '葬', '杂货', '五金', '传媒', '配件店', '应用服务', '妈妈', '助理', '新华书店', '卫视', '路店', '驾驶员培训', '道具', '世强', '小卖部', '待业', '医院', '外贸转卖', '培训', '会所', '趣味', '门诊', '资产管理', '日用品', '……', '资本', '礼仪', '商贸', '供电局', '管理局', '文化', '用户', '协会', '政府', '商旅', '展览会', '个体户', '食物', '小学', '云知声', '地铁店', '信用社', 'CCTV', '园林', '墓', '学校', '杂志', '区块链', '商店', '俱乐部', '财富', '食品', '股权', '便利店', '投资', '机关', '租赁', '茶业', '农夫', '种业', '职业技术学院', '连锁', '政界', '金属', '电商', '政治', 'Suffice Ind. Tech. Ltd.', '装潢', '犬业', '城管', '纤维', '新媒体', '交易中心', '经贸', '分店', '报纸', '#NAME?', '质量检测', '社区', '资讯', '劳务', '担保'}

print(e)

注意: 上面 e 内容在一行 未分行

然后直接运行该源文件, 就得到了以下报错:

1
SyntaxError: Non-UTF-8 code starting with '\xe7' in file  on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

为什么会出现这种报错呢?我们看看一位大佬的想法:

应该是Python在解析源码时出问题了,涉及到的代码在decoding_fgets。

Python 解析源码时通过 decoding_fgets 读取一行源码至 buffer 中,decoding_fgets 可能使用两种方式从文件中读取源码:

1.假如在文件开头指定了文件编码或者文件包含 utf-8 BOM,则使用 io.open以该编码打开文件,使用 readline 方法读取一行源码。

2.假如没有指定编码,则使用 Py_UniversalNewlineFgets 读取一行源码。

使用方式1读取源码没有任何问题。

当使用方式2时,Python 会通过valid_utf8检查读取到的代码的编码是不是合法的 utf8,一般情况下这也没有问题,但是 buffer 的初始长度是1024字节,如果一行代码太长(超过1023字节),则需要分多次读取,buffer 长度每次递增1024。运气差的情况下,分次读取时正好把一个汉字的字节给切分开,这就会导致编码错误。

我们按照第一种思路加上编码声明试下:

1
2
3
4
5
# -*- coding: utf-8 -*-

e = {'合作社', '经济', '财税', '账', '旅行社', '维修', '押运', '管理咨询', '基业', '养生', '雕塑', '上海警', '首饰', '商行', '电脑', '人才网', '素食', '日用制品', '铝制品', '百货', '银行', '产业园', '商学院', '驾驶培训', '生活', '潜水服务', '电视台', '贸易', '副食', '铝业', '风投', '财经', '警察协会', '试验', '展会', '金融', '陶艺', '营业部', '眼镜', '物业', '飞手', '实验', '幼教', '超市', '植保机用户', '农服', '教育', '会展', '销售', '果业', '保险', '生态园', '企业管理', '印刷', '电力局', '传播', '贷', '拆迁', '装饰', '养老', '人寿', '生活馆', '财务', '餐饮', '咨询服务', '出品', '个体', '办公', '自由职业', '动漫', '中央', '商务', '老年人', '农资', '新华社', '博览会', '新华网', '珠宝', '航展', '工贸', '专利', '市政', '体验', '网吧', '水敏纸检测喷潵效果', '破产', '大申网', '促进会', '酒业', '烟草', '家政', '威海警', '自来水', '代理', '售货', '创意', '基金', '进出口', '融资', '银联', '制衣', '暂无', '成人', '影视', 'VC', '英烈', '风水', '营销', '摄影', '小公司', '广告', '国贸', '服饰', '招聘', '创业', '新闻', '兽药', '体育节', '母婴', '还没定', '农村信用合作社', '人力', '国际货运', '职业技能', '知识产权', '酒店', '理发', '中财', '经营', '体检', '证券', '宾馆', '科贸', '经销', '个人', '报社', '宇辰世纪', '旅游', '展览', '演出', '宇辰网', '出版社', '媒体', '认证咨询', '电子商务', '孵化', '化妆', '职业学院', '拍卖', '葬', '杂货', '五金', '传媒', '配件店', '应用服务', '妈妈', '助理', '新华书店', '卫视', '路店', '驾驶员培训', '道具', '世强', '小卖部', '待业', '医院', '外贸转卖', '培训', '会所', '趣味', '门诊', '资产管理', '日用品', '……', '资本', '礼仪', '商贸', '供电局', '管理局', '文化', '用户', '协会', '政府', '商旅', '展览会', '个体户', '食物', '小学', '云知声', '地铁店', '信用社', 'CCTV', '园林', '墓', '学校', '杂志', '区块链', '商店', '俱乐部', '财富', '食品', '股权', '便利店', '投资', '机关', '租赁', '茶业', '农夫', '种业', '职业技术学院', '连锁', '政界', '金属', '电商', '政治', 'Suffice Ind. Tech. Ltd.', '装潢', '犬业', '城管', '纤维', '新媒体', '交易中心', '经贸', '分店', '报纸', '#NAME?', '质量检测', '社区', '资讯', '劳务', '担保'}

print(e)

这样的确不再报错了

第二种格式化代码试下
DbqLUs.png

这样也不再报错了

从这个问题我们学到了CPython读取源文件是这么读取的,如果按照 PEP8 规范老老实实写上 声明源文件编码的 Shebang(即使是 Python3 也应该如此), 代码规范按照 PEP8 限制下最大长度就不会出现这个问题。

知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!