记录一下 Python 源文件一行字符过长从而造成的问题.
首先声明下, 这个问题不是我遇到的, 是在刷华蟒的时候看到的一个帖子, 帖子地址在这儿, 有兴趣的可以看看
起因是帖主在源文件中定义了一个超长的集合, 该集合如下
e = {'合作社', '经济', '财税', '账', '旅行社', '维修', '押运', '管理咨询', '基业', '养生', '雕塑', '上海警', '首饰', '商行', '电脑', '人才网', '素食', '日用制品', '铝制品', '百货', '银行', '产业园', '商学院', '驾驶培训', '生活', '潜水服务', '电视台', '贸易', '副食', '铝业', '风投', '财经', '警察协会', '试验', '展会', '金融', '陶艺', '营业部', '眼镜', '物业', '飞手', '实验', '幼教', '超市', '植保机用户', '农服', '教育', '会展', '销售', '果业', '保险', '生态园', '企业管理', '印刷', '电力局', '传播', '贷', '拆迁', '装饰', '养老', '人寿', '生活馆', '财务', '餐饮', '咨询服务', '出品', '个体', '办公', '自由职业', '动漫', '中央', '商务', '老年人', '农资', '新华社', '博览会', '新华网', '珠宝', '航展', '工贸', '专利', '市政', '体验', '网吧', '水敏纸检测喷潵效果', '破产', '大申网', '促进会', '酒业', '烟草', '家政', '威海警', '自来水', '代理', '售货', '创意', '基金', '进出口', '融资', '银联', '制衣', '暂无', '成人', '影视', 'VC', '英烈', '风水', '营销', '摄影', '小公司', '广告', '国贸', '服饰', '招聘', '创业', '新闻', '兽药', '体育节', '母婴', '还没定', '农村信用合作社', '人力', '国际货运', '职业技能', '知识产权', '酒店', '理发', '中财', '经营', '体检', '证券', '宾馆', '科贸', '经销', '个人', '报社', '宇辰世纪', '旅游', '展览', '演出', '宇辰网', '出版社', '媒体', '认证咨询', '电子商务', '孵化', '化妆', '职业学院', '拍卖', '葬', '杂货', '五金', '传媒', '配件店', '应用服务', '妈妈', '助理', '新华书店', '卫视', '路店', '驾驶员培训', '道具', '世强', '小卖部', '待业', '医院', '外贸转卖', '培训', '会所', '趣味', '门诊', '资产管理', '日用品', '……', '资本', '礼仪', '商贸', '供电局', '管理局', '文化', '用户', '协会', '政府', '商旅', '展览会', '个体户', '食物', '小学', '云知声', '地铁店', '信用社', 'CCTV', '园林', '墓', '学校', '杂志', '区块链', '商店', '俱乐部', '财富', '食品', '股权', '便利店', '投资', '机关', '租赁', '茶业', '农夫', '种业', '职业技术学院', '连锁', '政界', '金属', '电商', '政治', 'Suffice Ind. Tech. Ltd.', '装潢', '犬业', '城管', '纤维', '新媒体', '交易中心', '经贸', '分店', '报纸', '#NAME?', '质量检测', '社区', '资讯', '劳务', '担保'}
print(e)
然后直接运行该源文件, 就得到了以下报错:
python test.py
File "test.py", line 3
SyntaxError: Non-UTF-8 code starting with '\xe7' in file test.py on line 3, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
然后我尝试着加上声明源文件编码的 Shebang # -*- coding: utf8 -*-
就好使了.
这就很有意思了, 为什么呢? 抱着有没有大神的回复继续往下翻, 果然, 大腿出现了.
研究了一下 Python3.6.6 的源码,我认为是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。运气差的情况下,分次读取时正好把一个汉字的字节给切分开,这就会导致编码错误。
然后我顺着大腿的思路给代码 Format 了一下, 果然可行…
e = {'合作社', '经济', '财税', '账', '旅行社', '维修', '押运', '管理咨询', '基业', '养生', '雕塑', '上海警', '首饰', '商行', '电脑', '人才网', '素食', '日用制品',
'铝制品', '百货', '银行', '产业园', '商学院', '驾驶培训', '生活', '潜水服务', '电视台', '贸易', '副食', '铝业', '风投', '财经', '警察协会', '试验', '展会',
'金融', '陶艺', '营业部', '眼镜', '物业', '飞手', '实验', '幼教', '超市', '植保机用户', '农服', '教育', '会展', '销售', '果业', '保险', '生态园', '企业管理',
'印刷', '电力局', '传播', '贷', '拆迁', '装饰', '养老', '人寿', '生活馆', '财务', '餐饮', '咨询服务', '出品', '个体', '办公', '自由职业', '动漫', '中央',
'商务', '老年人', '农资', '新华社', '博览会', '新华网', '珠宝', '航展', '工贸', '专利', '市政', '体验', '网吧', '水敏纸检测喷潵效果', '破产', '大申网', '促进会',
'酒业', '烟草', '家政', '威海警', '自来水', '代理', '售货', '创意', '基金', '进出口', '融资', '银联', '制衣', '暂无', '成人', '影视', 'VC', '英烈',
'风水', '营销', '摄影', '小公司', '广告', '国贸', '服饰', '招聘', '创业', '新闻', '兽药', '体育节', '母婴', '还没定', '农村信用合作社', '人力', '国际货运',
'职业技能', '知识产权', '酒店', '理发', '中财', '经营', '体检', '证券', '宾馆', '科贸', '经销', '个人', '报社', '宇辰世纪', '旅游', '展览', '演出', '宇辰网',
'出版社', '媒体', '认证咨询', '电子商务', '孵化', '化妆', '职业学院', '拍卖', '葬', '杂货', '五金', '传媒', '配件店', '应用服务', '妈妈', '助理', '新华书店',
'卫视', '路店', '驾驶员培训', '道具', '世强', '小卖部', '待业', '医院', '外贸转卖', '培训', '会所', '趣味', '门诊', '资产管理', '日用品', '……', '资本',
'礼仪', '商贸', '供电局', '管理局', '文化', '用户', '协会', '政府', '商旅', '展览会', '个体户', '食物', '小学', '云知声', '地铁店', '信用社', 'CCTV',
'园林', '墓', '学校', '杂志', '区块链', '商店', '俱乐部', '财富', '食品', '股权', '便利店', '投资', '机关', '租赁', '茶业', '农夫', '种业', '职业技术学院',
'连锁', '政界', '金属', '电商', '政治', 'Suffice Ind. Tech. Ltd.', '装潢', '犬业', '城管', '纤维', '新媒体', '交易中心', '经贸', '分店', '报纸',
'#NAME?', '质量检测', '社区', '资讯', '劳务', '担保'}
print(e)
这个时候加不加声明源文件编码的 Shebang 都不会报错
当然, 如果按照 PEP8 规范老老实实写上 声明源文件编码的 Shebang(即使是 Python3 也应该如此), 代码规范按照 PEP8 限制下最大长度就不会出现这个问题. 但是, 从Python解释器读取源文件的方面来说, 确实是涨芝士了, 原来是CPython读取源文件是这么读取的.
今天的文章Python源文件一行字符过长造成的问题分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21821.html