为了账号安全,请及时绑定邮箱和手机立即绑定

sys.setdefaultencoding('utf-8')的危险

sys.setdefaultencoding('utf-8')的危险

qq_花开花谢_0 2019-10-09 16:36:17
sys.setdefaultencoding('utf-8')在Python 2中存在一种令人沮丧的设置趋势。有人能列出与此相关的问题的真实示例吗?喜欢争执it is harmful或it hides bugs不健全,很有说服力。更新:请注意,此问题仅与有关utf-8,而不是与“一般情况下”更改默认编码有关。如果可以,请提供一些示例代码。
查看完整描述

3 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

因为您不总是希望将字符串自动解码为Unicode,或者为此,您的Unicode对象也会自动编码为字节。由于您要的是一个具体示例,因此这里是一个示例:


使用WSGI Web应用程序;您通过将外部过程的乘积循环添加到列表中来构建响应,并且该外部过程为您提供了UTF-8编码的字节:


results = []

content_length = 0


for somevar in some_iterable:

    output = some_process_that_produces_utf8(somevar)

    content_length += len(output)

    results.append(output)


headers = {

    'Content-Length': str(content_length),

    'Content-Type': 'text/html; charset=utf8',

}

start_response(200, headers)

return results

那很好,也很有效。但是随后您的同事出现并添加了新功能;您现在也提供了标签,这些标签已本地化:


results = []

content_length = 0


for somevar in some_iterable:

    label = translations.get_label(somevar)

    output = some_process_that_produces_utf8(somevar)


    content_length += len(label) + len(output) + 1

    results.append(label + '\n')

    results.append(output)


headers = {

    'Content-Length': str(content_length),

    'Content-Type': 'text/html; charset=utf8',

}

start_response(200, headers)

return results

您已经用英语测试过,一切仍然有效,太好了!


但是,该translations.get_label()库实际上返回Unicode值,并且在切换语言环境时,标签包含非ASCII字符。


WSGI库将这些结果写到套接字,并且所有Unicode值都会自动为您编码,因为您将其设置setdefaultencoding()为UTF-8,但是计算出的长度是完全错误的。这太短了,因为UTF-8会使用一个以上的字节来编码ASCII范围以外的所有内容。


所有这些都忽略了您实际上正在使用其他编解码器中的数据的可能性。您可能正在写Latin-1 + Unicode,但是现在您有一个不正确的长度标头和多种数据编码。


如果您不使用sys.setdefaultencoding()异常,将会引发一个异常,并且您知道自己有一个错误,但是现在您的客户抱怨抱怨响应不完整。页面末尾缺少字节,您不太了解这种情况。


请注意,这种情况甚至不涉及可能不依赖于默认仍然是ASCII的第三方库。该sys.setdefaultencoding()设置是global,适用于在解释器中运行的所有代码。您如何确定这些库中没有涉及隐式编码或解码的问题?


仅在处理ASCII数据时,Python 2在str和unicode类型之间隐式地进行编码和解码可以是有益且安全的。但是,您确实需要知道何时意外混合Unicode和字节字符串数据,而不是用全局画笔将其粘贴在石膏上并希望获得最佳效果。


查看完整回答
反对 回复 2019-10-09
  • 3 回答
  • 0 关注
  • 1661 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信