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

35

有一种趋势是不鼓励在Python 2中设置sys.setdefaultencoding('utf-8')。有人能列举一些实际问题的真实示例吗?像“它有害”或“它隐藏了错误”这样的论点听起来不太令人信服。

更新:请注意,此问题仅涉及utf-8,而不是“一般情况下”更改默认编码。

如果可以,请提供一些带有代码的示例。


你会如何使用它?如果你是在谈论修改sitecustomize.py文件,那么当代码在其他计算机上运行时,可能会出现错误。 - Padraic Cunningham
4
可能相关 https://mail.python.org/pipermail/python-dev/2009-August/091406.html 由于一些字符串对象现在会相等但不一定具有相同的哈希值,因此可能会产生奇怪的效果。 只要Unicode对象和字符串都是ASCII字符集,它们就具有相同的哈希值。 使用ASCII默认编码时,非ASCII字符串无法与Unicode对象进行比较,因此不会出现问题。 - Padraic Cunningham
5
如果你认为需要它的话,那么你误解了Python如何处理编码。这是正确使用它的演示: http://farmdev.com/talks/unicode/ 顺便说一句,如果"它可以隐藏错误"这个观点不让你信服,那么这可能才是真正的问题。(是的,在Python 2中使用Unicode很糟糕。但是sys.setdefaultencoding并不是解决方案。) 最后,如果你想看到它引起的错误,请参考这里:https://dev59.com/4V4b5IYBdhLWcg3w1UvL#28627705 - Konrad Rudolph
@techtonik 这里有一个问题的例子,其中一个用户因为PyDev的作者认为设置sys.setdefaultencoding('utf-8')是个好主意而受到了影响。这里有另一个博客文章,其中有更多细节和进一步链接,也有人因此受到了影响。文章链接:https://opensourcehacker.com/2010/01/24/aptana-studio-eclipse-pydev-default-unicode-encoding/ - Lukas Graf
3
以下是这篇关于“sys.setdefaultencoding()为什么会破坏代码”的优秀文章链接:https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/。 - Mark Tolonen
显示剩余4条评论
5个回答

25

原帖要求展示代码以证明开关是有害的——但除了与开关无关的错误会被“隐藏”之外。

更新

  • [2020-11-01]: pip install setdefaultencoding
    消除了需要从Thomas Grainger重新加载sys的需求。

  • [2019]: 个人使用python3的经验:

    • 没有Unicode编码问题。原因是:
    • 习惯了一天写100次.encode('utf-8').decode('utf-8')
    • 查看库: 相同。在几乎所有的I/O中,'utf-8'要么是硬编码的,要么是默认的静默方式。
    • 大幅改善了字节字符串支持,使得像mercurial这样的I/O中心应用程序最终成为可能。
    • 不得不一直写.encode和.decode让人们意识到了人类和机器之间字符串的差异。
在我看来,Python2的字节串结合(UTF-8默认)仅在输出给人类或Unicode格式之前解码是技术上更优越的方法,与在入口和出口处对所有内容进行多次编码/解码相比。这取决于应用程序,如果像len()函数一样返回用于存储和转发机器的字节数,而不是返回人类的字符数,那么这种方法可能更实用。
=> 我认为可以放心地说, UTF-8无处不在拯救了 Unicode三明治设计。没有它,许多只传递字符串而不解释它们的库和应用程序将无法工作。

结论摘要

(来自2017年)

基于我的经验和收集到的证据,我得出了以下结论。

  1. 将默认编码设置为UTF-8现在是安全的,除了处理来自非unicode准备系统的文件的专业应用程序。

  2. "官方"拒绝转换的理由对于绝大多数最终用户(而不是库提供者)已经不再相关,因此我们应该停止阻止用户进行设置。

  3. 在默认情况下正确处理Unicode的模型比手动使用Unicode API更适合于应用程序进行系统间通信。

实际上,经常修改默认编码可以避免在绝大多数情况下出现用户困扰。是的,有时处理多个编码的程序会默默地出现错误,但由于这个开关可以逐步启用,所以这不是最终用户代码中的问题。

更重要的是,启用此标志对用户代码来说是一个真正的优势,既可以减少手动处理Unicode转换、混乱代码和降低可读性的开销,也可以避免程序员在所有情况下未能正确处理这一问题时可能出现的错误。

由于这些说法几乎与Python官方的沟通方式完全相反,我认为有必要对这些结论进行解释。

成功使用修改后的默认编码的示例

  1. Dave Malcom of Fedora believed it is always right. He proposed, after investigating risks, to change distribution wide def.enc.=UTF-8 for all Fedora users.

    Hard fact presented though why Python would break is only the hashing behavior I listed, which is never picked up by any other opponent within the core community as a reason to worry about or even by the same person, when working on user tickets.

    Resume of Fedora: Admittedly, the change itself was described as "wildly unpopular" with the core developers, and it was accused of being inconsistent with previous versions.

  2. There are 3000 projects alone at openhub doing it. They have a slow search frontend, but scanning over it, I estimate 98% are using UTF-8. Nothing found about nasty surprises.

  3. There are 18000(!) github master branches with it changed.

    While the change is "unpopular" at the core community its pretty popular in the user base. Though this could be disregarded, since users are known to use hacky solutions, I don't think this is a relevant argument due to my next point.

  4. There are only 150 bugreports total on GitHub due to this. At a rate of effectively 100%, the change seems to be positive, not negative.

    To summarize the existing issues people have run into, I've scanned through all of the aforementioned tickets.

    • Chaging def.enc. to UTF-8 is typically introduced but not removed in the issue closing process, most often as a solution. Some bigger ones excusing it as temporary fix, considering the "bad press" it has, but far more bug reporters are justglad about the fix.

    • A few (1-5?) projects modified their code doing the type conversions manually so that they did not need to change the default anymore.

    • In two instances I see someone claiming that with def.enc. set to UTF-8 leads to a complete lack of output entirely, without explaining the test setup. I could not verify the claim, and I tested one and found the opposite to be true.

    • One claims his "system" might depend on not changing it but we do not learn why.

    • One (and only one) had a real reason to avoid it: ipython either uses a 3rd party module or the test runner modified their process in an uncontrolled way (it is never disputed that a def.enc. change is advocated by its proponents only at interpreter setup time, i.e. when 'owning' the process).

  5. I found zero indication that the different hashes of 'é' and u'é' causes problems in real-world code.

  6. Python does not "break"

    After changing the setting to UTF-8, no feature of Python covered by unit tests is working any differently than without the switch. The switch itself, though, is not tested at all.

  7. It is advised on bugs.python.org to frustrated users

    Examples here, here or here (often connected with the official line of warning)

    The first one demonstrates how established the switch is in Asia (compare also with the github argument).

  8. Ian Bicking published his support for always enabling this behavior.

    I can make my systems and communications consistently UTF-8, things will just get better. I really don't see a downside. But why does Python make it SO DAMN HARD [...] I feel like someone decided they were smarter than me, but I'm not sure I believe them.

  9. Martijn Fassen, while refuting Ian, admitted that ASCII might have been wrong in the first place.

    I believe if, say, Python 2.5, shipped with a default encoding of UTF-8, it wouldn't actually break anything. But if I did it for my Python, I'd have problems soon as I gave my code to someone else.

  10. In Python3, they don't "practice what they preach"

    While opposing any def.enc. change so harshly because of environment dependent code or implicitness, a discussion here revolves about Python3's problems with its 'unicode sandwich' paradigm and the corresponding required implicit assumptions.

    Further they created possibilities to write valid Python3 code like:

     >>> from 褐褑褒褓褔褕褖褗褘 import *        
     >>> def 空手(合氣道): あいき(ど(合氣道))
     >>> 空手(う힑힜(' ') + 흾)
     
    
  11. DiveIntoPython recommends it.

  12. In this thread, Guido himself advises a professional end user to use a process specific environt with the switch set to "create a custom Python environment for each project."

    The fundamental reason the designers of Python's 2.x standard library don't want you to be able to set the default encoding in your app, is that the standard library is written with the assumption that the default encoding is fixed, and no guarantees about the correct workings of the standard library can be made when you change it. There are no tests for this situation. Nobody knows what will fail when. And you (or worse, your users) will come back to us with complaints if the standard library suddenly starts doing things you didn't expect.

  13. Jython offers to change it on the fly, even in modules.

  14. PyPy did not support reload(sys) - but brought it back on user request within a single day without questions asked. Compare with the "you are doing it wrong" attitude of CPython, claiming without proof it is the "root of evil".


结束这个列表,我确认可以构建一个模块,由于更改了解释器配置而崩溃,就像这样做:
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):
    <code relying on mystr to be ASCII>

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

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


4
这应该是一篇博客文章,你可以在评论中链接到Martijn的回答。 - Wayne Conrad
7
这篇回答太长了,而且并非必要。你所提供的大部分支持论点,也就是占据了帖子大部分空间的那些观点,最多只能算是 民意论证,最糟糕的情况则属于 臆言推理。此外,关于标准化和编码的整个部分与问题无关,应该在博客文章中讨论,而不是放在 Stack Overflow 的答案中。如果你仅简要阐述你的 技术观点,那么你的答案会更好。 - Alexis King
2
一些具体的评论:设置不同的默认值就像使用goto。当然,你可以让它工作,但是在开发应用程序时会更加困难。您将无法一致地处理Unicode,这将会对您产生影响。大多数使用它的人了解Unicode,并认为这是简单的解决方法。 - Martijn Pieters
2
许多 GitHub 代码使用的参数并不意味着这样做是正确的,这也可以被视为大多数开发人员不理解如何正确使用 Unicode 的证明。您可以在经验不足的开发人员如何使用 super()中看到相同的问题。一般来说,这是一种货物崇拜,应用和误用而不理解它是如何工作的或是否需要。 - Martijn Pieters
1
你说得对,通常情况下,不应该改变默认设置,因为问题会神奇地消失,而你并不知道原因。你应该知道自己在做什么。但是如果你知道它的作用,那么Python2就比Py3更好用。对我来说更好 - 但这是另外一个故事;-) - Red Pill
显示剩余11条评论

16

因为您并不总是希望自动将字符串解码为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(),那么就会引发异常,你就知道出现了一个bug,但现在你的客户抱怨响应不完整;页面末尾缺失了一些字节,你不确定发生了什么。

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

当你处理仅涉及ASCII数据时,Python 2会自动将 strunicode 类型之间进行编解码,这可能是有帮助和安全的。但是,当你意外混合使用Unicode和字节字符串数据时,你真的需要知道,而不是用全局方法掩盖它并希望一切顺利。


1
@techtonik:在我的示例中,translations.get_label() 返回 unicode 对象。WSGI 实现也可以选择仅连接所有结果,此时您将获得一个 unicode 对象作为输出传递给套接字,或者可能传递给另一个 WSGI 包装标签。我们不知道,因为我们消除了通常会抛出的所有 Python 异常。 - Martijn Pieters
4
@techtonik: 我们正在打转。你认为这并不是坏事,因为你没有意识到隐式类型转换可能会带来的问题。在一种隐式转换只是例外而不是默认的语言中,这是一个巨大的问题,而你正在全局级别改变该转换规则。如果这是按模块配置的话,你可以自由地为自己惹上麻烦,而不会迫使任何第三方库也采用同样的规则。但实际情况并非如此,如果你无法看到这种行为有问题,我就不知道该怎么说了。 - Martijn Pieters
2
你计算的长度完全是错误的,这是一个好的论据。http://pastebin.ubuntu.com/10791721/在控制台上输出3和6。但这看起来像是Python中的一个bug,无法处理多字节编码。 - anatoly techtonik
6
为什么Python处理多字节编码时会出现错误呢?Unicode字符串的长度应该是代码点的数量,而不是任意编解码器中字节的数量。字节字符串的长度应该是字节的数量。内容长度头应包含字节数,而不是代码点数。我不明白为什么这是多字节与单字节编码问题。 - Martijn Pieters
4
使用Jinja2揭示了Roundup没有实践Unicode三明治方法;尽早在应用程序的入口点将所有文本设置为unicode,并尽可能晚地在退出点将其编码为字节。 在这种情况下,我建议阅读/观看Ned Batchelder的Pragmatic Unicode演示文稿 - Martijn Pieters
显示剩余13条评论

3
首先:许多反对更改默认编码的人认为这是愚蠢的,因为它甚至会改变ASCII比较。
我认为公平地说明一下,遵循原始问题,我看不到有人提倡除了从ASCII偏离到UTF-8之外的任何其他做法。
那些反对更改它的人似乎总是拿出setdefaultencoding('utf-16')的例子。;-)

有 m = {'a': 1, 'é': 2} 和文件 'out.py':

# coding: utf-8
print u'é' 

然后:

+---------------+-----------------------+-----------------+
| DEF.ENC       | OPERATION             | RESULT (printed)|            
+---------------+-----------------------+-----------------+
| ANY           | u'abc' == 'abc'       | True            |     
| (i.e.Ascii    | str(u'abc')           | 'abc'           |
|  or UTF-8)    | '%s %s' % ('a', u'a') | u'a a'          | 
|               | python out.py         | é               |
|               | u'a' in m             | True            |
|               | len(u'a'), len(a)     | (1, 1)          |
|               | len(u'é'), len('é')   | (1, 2) [*]      |
|               | u'é' in m             | False  (!)      |
+---------------+-----------------------+-----------------+
| UTF-8         | u'abé' == 'abé'       | True   [*]      |
|               | str(u'é')             | 'é'             |
|               | '%s %s' % ('é', u'é') | u'é é'          | 
|               | python out.py | more  | 'é'             |
+---------------+-----------------------+-----------------+
| Ascii         | u'abé' == 'abé'       | False, Warning  |
|               | str(u'é')             | Encoding Crash  |
|               | '%s %s' % ('é', u'é') | Decoding Crash  |
|               | python out.py | more  | Encoding Crash  |
+---------------+-----------------------+-----------------+

[*]: 结果假设é的值是相同的。请参见下文。
当查看这些操作时,更改程序中的默认编码可能看起来不太糟糕,让您获得与ASCII字符仅数据“更接近”的结果。
关于哈希(in)和len()行为,您会得到与ASCII相同的结果(更多结果请参见下面)。这些操作还显示了Unicode字符串和字节字符串之间存在重大差异,如果忽略它们可能会导致逻辑错误。
如已注意到的:这是一个全局选项,因此您只有一次选择机会 - 这就是为什么库开发人员真的永远不应该这样做,而应该使其内部有序,以便他们不需要依赖Python的隐式转换。 他们还需要清楚地记录他们期望的返回内容,并拒绝他们没有编写库的输入(例如normalize函数,请参见下文)。
=>在打开此设置的情况下编写程序,使得其他人在其代码中使用程序的模块变得有风险,至少需要过滤输入。
注意:一些反对者声称def.enc.甚至是系统范围的选项(通过sitecustomize.py),但最新的软件容器化时代(docker)中,每个进程都可以在其完美环境中启动,无需额外负担。
关于哈希和len()的行为:
这告诉你,即使修改了def.enc.,你仍然不能忽视在程序中处理的字符串类型。u''和''是内存中不同的字节序列 - 通常情况下是如此。
因此,在测试时,请确保您的程序在处理非ASCII数据时也能正确运行。
有人说哈希值可能会因数据值更改而变得不相等 - 尽管由于隐式转换,'=='操作仍然相等 - 这是反对更改def.enc.的一个论点。
我个人不认同这一观点,因为哈希行为与未更改时保持一致。我还没有看到过在我“拥有”的进程中由于该设置而导致不良行为的令人信服的例子。
总的来说,关于setdefaultencoding("utf-8"):是否愚蠢的答案应更加平衡。
这取决于情况。
虽然它确实避免了例如在日志语句中的str()操作中的崩溃 - 但代价是后期出现意外结果的机会更大,因为错误的类型会进入依赖于某种类型的代码中。
无论如何,它都不应该成为学习字节字符串和Unicode字符串之间区别的替代方法。
最后,将默认编码设置为非Ascii并不会使常见文本操作(如len(),切片和比较)变得更容易 - 如果你认为用UTF-8将所有内容转换成字节字符串可以解决问题,那就大错特错了。
不幸的是,通常情况下这并不起作用。
'==' 和 len() 的结果要比人们想象的复杂得多 - 即使在两侧类型相同的情况下。
如果没有改变默认编码,“==”对于非Ascii总是失败的,就像表格中所示。但是,有时它确实可以工作:
Unicode标准化了世界上一百万个符号,并给它们分配了一个编号 - 但是在输出设备中向用户显示的图形与它们生成的符号之间不幸地没有1:1的双射关系。
为了激励你研究这个:假设有两个文件j1、j2,使用相同的编码和同一个程序编写,包含用户输入。
>>> u1, u2 = open('j1').read(), open('j2').read()
>>> print sys.version.split()[0], u1, u2, u1 == u2

结果:2.7.9 José José False(!)
在Py2中使用print作为函数,您会看到原因:不幸的是,有两种编码相同的字符,带重音符号的“e”:
>>> print (sys.version.split()[0], u1, u2, u1 == u2)
('2.7.9', 'Jos\xc3\xa9', 'Jose\xcc\x81', False)

“你可能会说这是一个愚蠢的编解码器,但这并不是编解码器的问题。这是Unicode本身存在的问题。”
“因此,即使在Py3中:”
>>> u1, u2 = open('j1').read(), open('j2').read()
>>> print sys.version.split()[0], u1, u2, u1 == u2

结果:3.4.2 José José False(!)
=> 无论您使用哪种计算语言,这都与Py2和Py3无关:要编写优质软件,您可能需要“规范化”所有用户输入。 Unicode标准确实标准化了规范化。在Python 2和3中,unicodedata.normalize函数是您的朋友。

1
你假设你的源代码也是以UTF-8编码的。或者说,所有的字节字符串都是UTF-8编码的。从Unicode到UTF-8的隐式编码,然后使用任意编码将该数据与任何其他字节字符串连接起来,这将是一个巨大的错误,并且你通过设置默认编码来掩盖了它。 - Martijn Pieters
1
另一个问题是代码可能会依赖于编码或解码错误来表示类型差异,包括第三方库。通过设置除ASCII以外的默认编码,您将无法再检测到UTF-8字节-> Unicode和Unicode->字节的隐式编码,而您实际上想要使用显式编码。 - Martijn Pieters
1
无论如何,我还没有遇到过一种情况,在这种情况下,设置默认编码比正确处理编码更好的想法。这就像使用全局变量一样,你不使用它们,因为在实践中,你会显著增加错误的可能性。 - Martijn Pieters
1
没错 - 我发帖的目的是要明确以下几点:
  1. 对于这个问题的答案应该更加平衡。
  2. def.enc = utf-8并不能使开发人员免除理解字节和Unicode字符串差异的责任 - 这对于他自己的代码来说很重要。
  3. 质量文本处理比新手想象的要复杂得多,即使是像len()和比较这样的原子操作。
- Red Pill
1
我认为,对于拒绝Python 1.x的态度是一种分类错误,特别是在存在大量遗留代码的情况下 - 我敢说,很多现有的Py2代码都是由于需要解决文本处理之外的具体问题而编写的,其中包含了大量的str()操作... 此外,像Go和Rust这样时髦的语言证明,可以在“utf-8字节字符串三明治”中工作,并仅在必要时使用Unicode函数。 - Red Pill
显示剩余4条评论

2

实际例子 #1

它在 单元测试 中无法工作。

测试运行器 (nose, py.test, ...) 首先初始化 sys,然后才发现并导入你的模块。到那时,改变默认编码已经太晚了。

同样的,如果有人将你的代码作为模块运行,它也无法工作,因为他们的初始化先进行。

是的,混合使用 strunicode 并仅依赖于隐式转换只会将问题推迟到更后面。


1
单元测试模块引入了设置 sys.defaultencoding('utf-8') 的主模块,那么为什么它不起作用呢? - anatoly techtonik
sys.setdefaultencoding() 不会设置输入或输出编码;我认为你误解了这个函数的作用。它设置了当混合使用 unicodestr 类型时,隐式地unicode 编码为 str 或将 str 解码为 unicode 所使用的编解码器。 - Martijn Pieters
无论它是否适用于单元测试,取决于与第三方库相同的因素;如果代码依赖于ASCII作为默认值,则这些测试可能会失败,因为该默认值已在全局范围内更改。 - Martijn Pieters
@techtonik 关于混合模块的问题。其他模块已经先被加载,它们已经导入了 sys。当你的模块运行时,改变编码已经为时过晚。可用的解决方法是 sitecustomize.pyreload(sys)。前者无法与单元测试一起使用,也不可组合。后者是黑魔法,需要自己承担风险。 - Dima Tisnek
实际上,stdio是基于PYTHONIOENCODING和locale进行初始化的。感谢@MartijnPieters。 - Dima Tisnek
显示剩余4条评论

1

我们需要知道的一件事是

Python 2使用sys.getdefaultencoding()strunicode之间进行解码/编码。

conversion between str and unicode

所以如果我们更改默认编码,就会出现各种不兼容问题。例如:

# coding: utf-8
import sys

print "你好" == u"你好"
# False

reload(sys)
sys.setdefaultencoding("utf-8")

print "你好" == u"你好"
# True

更多例子:

说到这里,我记得有一些博客建议尽可能使用Unicode,只有在处理I/O时才使用位串。我认为如果你遵循这个惯例,生活会变得更容易。更多的解决方案可以在以下找到:

1
从上面我观察到,我们必须始终使用sys.setdefaultencoding("utf-8")才能使"你好" == u"你好"成立,这是正确的。 - nehem
1
@nehemiah:没错!!就像3 == 3.0也是True一样。相等性是关于信息本身的陈述,而不是关于它包装成哪种数据类型的。 - Red Pill
1
2018年了,我依然觉得这很疯狂,因为这些人多年来一直拒绝让python加上def.enc utf-8开关,也拒绝修复类似这样的错误行为,因为他们认为那会很“危险”...>>> print "abc" == u"abc" => True >>> print "你bc" == u"你bc" => False...这些人在他们的unicode三明治理念中,接受几乎任何Python3中I/O库的静默decode('utf-8') - Red Pill
1
@JiacaiLiu: http://utf8everywhere.org/ - Unicode三明治的想法,即在I/O时不必要地解码所有文本值(并将其留给I/O库在任何地方默默地执行decode('utf-8')),与在需要人类语义值的情况下使用Unicode作为API相比,这种想法是错误的,而这种情况在计算中很少出现。此外,在微服务无处不在的时代,I/O无处不在,处理管道内的系统关心的是文本值的存在,而不是它们对人类的语义意义。解码毫无意义,并且在99%的情况下容易出错。 - Red Pill
@JiacaiLiu,你指的“solution”是哪一个?我注意到在Python 2中与Unicode交互的唯一解决方案是通过sys.setdefaultencoding("utf-8") - nehem
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接