热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《sys.setdefaultencoding('utf-8')的危险》经验,为你挑选了2个好方法。

sys.setdefaultencoding('utf-8')在Python 2中存在令人沮丧的设置趋势.任何人都可以列出问题的真实例子吗?论证喜欢it is harmfulit hides bugs听起来不太令人信服.

更新:请注意,这个问题只是关于utf-8,它不是关于改变默认编码"一般情况下".

如果可以,请举一些代码示例.



1> Red Pill..:

原始海报要求提供代码,证明交换机是有害的 - 除了它"隐藏"与交换机无关的错误.

结论摘要

根据我收集的经验和证据,以下是我得出的结论.

    现在将defaultencoding设置为UTF-8是安全的,除了专门的应用程序,处理来自非unicode就绪系统的文件.

    对交换机的"官方"拒绝是基于绝大多数最终用户(不是图书馆提供商)不再相关的原因,因此我们应该停止阻止用户进行设置.

    默认情况下,在正确处理Unicode的模型中工作比手动使用unicode API 更适合于系统间通信的应用程序.

实际上,非常频繁地修改默认编码可以避免绝大多数用例中的许多用户头痛.是的,在某些情况下处理多种编码的程序会默默地行为不端,但由于这种切换可以零散启用,因此这不是最终用户代码中的问题.

更重要的是,启用此标志是一个真正的优势,是用户的代码,既可以减少必须手动处理Unicode转换的开销,使代码混乱并使其可读性降低,又可以避免程序员无法执行此操作时的潜在错误在所有情况下都适当.


由于这些声明几乎完全与Python的官方通信线路相反,我认为对这些结论的解释是有道理的.

在野外成功使用修改后的defaultencoding的示例

    Fedora的Dave Malcom认为它总是正确的.在调查风险之后,他建议改变所有 Fedora用户的分布范围def.enc.= UTF-8 .

    虽然提出了铁的事实,为什么 Python的将打破只有散列行为我上市,这是从来没有在核心社区内拾起任何其他对手的理由担心,甚至由同一个人,在用户票工作时.

    Fedora的简历:不可否认,变更本身被核心开发人员描述为"非常不受欢迎",并被指责与先前版本不一致.

    有独自3000个项目在openhub做.他们有一个慢搜索前端,但扫描它,我估计98%使用UTF-8.没有发现令人讨厌的惊喜.

    有18000(!)个github主分支,它改变了.

    虽然这种变化在核心社区" 不受欢迎 ",但在用户群中非常受欢迎.虽然这可以被忽视,但由于已知用户使用hacky解决方案,我认为这不是一个相关的论点,因为我的下一个观点.

    由于这个原因,GitHub上只有150个bug报告.以实际100%的速度,变化似乎是积极的,而不是消极的.

    总结人的存在的问题碰上了,我已经通过上述所有门票扫描.

    Chaging def.enc.UTF-8通常是在问题结束过程中引入但未删除的,通常作为解决方案.一些较大的人原谅它作为临时的解决办法,考虑到"坏消息"有,但更臭虫记者都只是很高兴关于修复.

    一些(1-5?)项目修改了他们的代码手动进行类型转换,因此他们不再需要更改默认值.

    在两个例子中,我看到有人声称使用def.enc.设置为UTF-8导致完全缺乏产量的 完全,没有解释的测试设置.我无法验证声明,我测试了一个并发现相反的情况属实.

    有人声称他的"系统"可能取决于不改变它,但我们不知道为什么.

    一个(且只有一个),有一个真正的理由,以避免它:IPython中或采用第三方模块或测试运行修改其过程以不受控制的方式(这是从来没有争议,一个def.enc变化是由它的主张.支持者只在翻译设置时,即"拥有"过程时).

    我发现零指示"é"和"u'é"的不同哈希值会导致现实世界代码出现问题.

    Python 没有 "破解"

    将设置更改为UTF-8后,单元测试所涵盖的Python功能与​​没有交换机的情况完全不同.但是,开关本身根本没有经过测试.

    在bugs.python.org上建议沮丧的用户

    此处,此处或此处的示例 (通常与官方警告线相关)

    第一个演示了交换机在亚洲的建立程度(与github参数相比).

    Ian Bicking 发布了他对始终启用此行为的支持.

    我可以使我的系统和通信始终保持UTF-8,事情会变得更好.我真的没有看到一个缺点.但是为什么Python让它变得如此艰难[...]我觉得有人认为他们比我聪明,但我不确定我是否相信他们.

    Martijn Fassen在反驳Ian时承认,ASCII首先可能是错误的.

    我相信,如果说Python 2.5附带了UTF-8的默认编码,它实际上不会破坏任何东西.但如果我为我的Python做了这件事,我很快就会遇到问题,因为我把代码交给了其他人.

    在Python3中,他们不"实践他们所宣扬的"

    反对任何def.enc.由于依赖于环境的代码或隐含性而变得非常严厉,这里的讨论围绕着Python3的'unicode sandwich'范式和相应的必要隐含假设的问题.

    此外,他们创建了编写有效Python3代码的可能性,如:

    >>> from ????????? import *        
    >>> def ??(???): ???(?(???))
    >>> ??(???(' ') + ?)
    
    

    DiveIntoPython 推荐它.

    在这个线程,圭多自己建议一个专业最终用户使用过程中的具体environt设置为开关"为每个项目创建一个自定义的Python环境."

    Python的2.x标准库的设计者不希望您能够在应用程序中设置默认编码的根本原因是标准库的编写假设默认编码是固定的,并且不保证更改标准库时,可以正确运行.这种情况没有测试.没人知道什么会失败.如果标准库突然开始做你没想到的事情,那么你(或者更糟的是,你的用户)会回复我们.

    Jython提供即时在模块中即时更改它.

    PyPy 不支持reload(sys) - 但是在没有问题的情况下在一天内将其恢复为用户请求.与CPython 的" 你做错了 "的态度相比,声称没有证据就是"邪恶的根源".


结束此列表我确认可以构造一个因为更改的解释器配置而崩溃的模块,执行如下操作:

def is_clean_ascii(s):
    """ [Stupid] type agnostic checker if only ASCII chars are contained in s"""
    try:
        unicode(str(s))
        # we end here also for NON ascii if the def.enc. was changed
        return True
    except Exception, ex:
        return False    

if is_clean_ascii(mystr):
    

我不认为这是一个有效的论点,因为编写这种双类型接受模块的人显然知道ASCII与非ASCII字符串,并且会注意编码和解码.

我认为这个证据足以表明,在绝大多数情况下,更改此设置不会导致现实世界代码库中出现任何问题.


这个答案实在太长了,而且不必要.大部分的论据,会占用你的大部分职位的那些,似乎充其量仅此而已的[诉诸群众(https://en.wikipedia.org/wiki/Argumentum_ad_populum)和[证明最后的详细信息(https://en.wikipedia.org/wiki/Proof_by_intimidation).此外,关于标准化和编码的整个部分是无关紧要的,属于博客文章,而不是Stack Overflow的答案.如果您只是简单地提出*技术原因*,那么您的答案会更好.
这不应该是您在评论Martijn答案时链接到的博客条目吗?
一些特定的注释:设置不同的默认值就像使用`goto`.当然,你可以使它工作,但在开发应用程序时你会有更难的时间.你在处理Unicode方面会有所不一致,这会让你感到困惑.大多数使用它的人不会*理解Unicode,并认为这是一个简单的方法.
许多GitHub代码使用它的论据并不能证明它可以使用,它也可以作为证据,大多数开发人员不理解如何正确使用Unicode.你看到[缺乏经验的开发人员如何使用`super()`的相同问题(/sf/ask/17360801/#19609168).一般来说,它是[*Cargo Cult*](http://en.wikipedia.org/wiki/Cargo_cult),在不理解*如何工作*或者根本不需要的情况下应用和误用.

2> Martijn Piet..:

因为您并不总是希望将字符串自动解码为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()设置是全局的,适用于在解释器中运行的所有代码.您是否确定那些涉及隐式编码或解码的库中没有问题?

当您仅处理ASCII数据时,Python 2在其间strunicode类型之间进行编码和解码可能是有用且安全的.但是你真的需要知道什么时候你不小心混合了Unicode和字节串数据,而不是用全局画笔涂抹它并希望最好.


@techtonik:为什么Python处理多字节编码的错误?Unicode字符串的长度应该是代码点的数量,而不是任意编解码器中的字节数.字节串的长度应该是字节数.Content Length标头应包含字节数,而不是代码点数.我不明白为什么这是一个多字节与单字节编码问题.
@techtonik:我们围成一圈.你不认为这很糟糕,因为你没有看到隐式转换类型是多么糟糕.在隐式转换是异常而不是默认转换的语言中,这是一个**巨大的**问题,并且您正在全局级别更改该转换的规则.如果这是为每个模块配置的话,你可以自由地射击自己,而不会强迫你使用任何第三方库的问题.但这不是这里的情况,如果你没有看到这种行为的问题,我不知道该告诉你什么.
@techtonik:在这里使用Jinja2揭示了Roundup没有实践*Unicode三明治*方法; 尽可能早地在入口点的应用程序`unicode`中生成*all text*,并且只在出口点编码为字节,尽可能晚.在这种情况下,我建议阅读/观看Ned Batchelder的[实用Unicode演示](http://nedbatchelder.com/text/unipain.html).
"你计算的长度是完全错误的"是一个很好的论据.http://pastebin.ubuntu.com/10791721/在控制台上给出了3和6.但这看起来像Python中的一个错误,它无法处理mutibyte编码.
推荐阅读
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 无损压缩算法专题——LZSS算法实现
    本文介绍了基于无损压缩算法专题的LZSS算法实现。通过Python和C两种语言的代码实现了对任意文件的压缩和解压功能。详细介绍了LZSS算法的原理和实现过程,以及代码中的注释。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • MATLAB函数重名问题解决方法及数据导入导出操作详解
    本文介绍了解决MATLAB函数重名的方法,并详细讲解了数据导入和导出的操作。包括使用菜单导入数据、在工作区直接新建变量、粘贴数据到.m文件或.txt文件并用load命令调用、使用save命令导出数据等方法。同时还介绍了使用dlmread函数调用数据的方法。通过本文的内容,读者可以更好地处理MATLAB中的函数重名问题,并掌握数据导入导出的各种操作。 ... [详细]
author-avatar
fuhuan9479184787
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有