Python和Unicode:一切都应该是Unicode

use*_*312 22 python unicode bytestring

原谅如果这是一个很长的问题:

我用Python编程了大约六个月.自学,从Python教程开始,然后是SO,然后只使用谷歌的东西.

这是悲伤的部分:没有人告诉我所有字符串都应该是Unicode.不,我不是在撒谎或说谎,但教程在哪里提到它?我也看到大多数示例只是使用byte strings,而不是Unicode strings.我只是浏览并在SO上遇到这个问题,它说明Python中的每个字符串应该是一个Unicode字符串.这让我哭了!

我读到默认情况下Python 3.0中的每个字符串都是Unicode,所以我的问题是2.x:

  1. 我应该这样做:

    print u'Some text'还是只是print 'Text'

  2. 一切都应该是Unicode,这是否意味着,就像说我有一个tuple:

    t = ('First', 'Second'), it should be t = (u'First', u'Second')?

    我读过我可以做一个from __future__ import unicode_literals然后每个字符串都是一个Unicode字符串,但是我应该在容器内执行此操作吗?

  3. 读/写文件时,我应该使用该codecs模块.对?或者我应该使用标准方式或阅读/写作和/ encodedecode在需要的地方?

  4. 如果我从中获取字符串raw_input(),我应该将其转换为Unicode吗?

在2.x中处理所有上述问题的常用方法是什么?该from __future__ import unicode_literals声明?

对不起是一个这样的菜鸟,但这改变了我长期以来一直在做的事情,所以我很困惑.

Gle*_*ard 14

"始终使用Unicode"建议主要是为了更容易地过渡到Python 3.如果你的代码中有很多非Unicode字符串访问,那么移植它需要更多的工作.

此外,您不必根据具体情况决定字符串是否应存储为Unicode.您不必更改字符串的类型及其语法,因为您也改变了它们的内容.

使用错误的字符串类型也很容易,导致代码主要工作,或者代码在Linux中运行但不在Windows中运行,或者在一个语言环境中运行,而不是在另一个语言环境中运行.例如,for c in "??"在UTF-8语言环境中,将迭代每个UTF-8字节(所有六个字节),而不是每个字符; 是否打破了事情取决于你对他们做了什么.

原则上,如果你使用Unicode字符串,什么都不应该破坏,但如果你不应该使用常规字符串,事情可能会中断.

然而,在实践中,在Python 2 codecs.open中使用Unicode字符串是一种痛苦. 不会自动选择正确的语言环境; 这失败了:

codecs.open("blar.txt", "w").write(u"??")
Run Code Online (Sandbox Code Playgroud)

真正的答案是:

import locale, codecs
lang, encoding = locale.getdefaultlocale()
codecs.open("blar.txt", "w", encoding).write(u"??")
Run Code Online (Sandbox Code Playgroud)

...这很麻烦,迫使人们只是打开文件来制作辅助功能. codecs.open 应该locale没有指定时自动使用编码; Python无法使这么简单的操作变得方便,这是人们通常不在任何地方使用Unicode 的原因之一.

最后,请注意在某些情况下,Unicode字符串在Windows中更为重要.例如,如果您使用的是西部语言环境,并且您有一个名为"汉字"的文件,则必须使用Unicode字符串来访问它,例如.os.stat(u"??").使用非Unicode字符串访问它是不可能的; 它只是看不到文件.

因此,原则上我会说Unicode字符串建议是合理的,但有一点需要注意,我自己一般都不遵循它.

  • @Phillipp:当然可以; 我没有义务为此跳出箍,特别是当它影响这么少的用户时.如果他们想要我的软件支持,他们可以付钱给我(或我的雇主)跳过这些箍,或游说Python来修复脑力激荡; 与UTF-8相比,*宽泛编码的整个点是不必处理的.像[s [0:20] +'...'`这样的每一段代码都受此影响; Python的错误在于允许这种模糊,难以测试的语言不一致而不是在UCS4上进行稳固的标准化.我只会在必要时担心. (2认同)
  • -1"始终使用Unicode"建议主要是为了更容易过渡到Python 3." 这是不真实的.一切都应该是unicode,因为你的程序不是在20世纪70年代的美国运行. (2认同)

Len*_*bro 11

不,不是每个字符串"都应该是Unicode".在Python代码中,您知道字符串文字是否需要是Unicode,因此将每个字符串文字都设置为Unicode文字没有任何意义.

但是有些情况下你应该使用Unicode.例如,如果您有任意文本输入,请使用Unicode.你迟早会找到一个使用它的非美国人,而且他想在这里找到一个非常好的人.除非您的输入和输出碰巧使用相同的编码,否则您将遇到问题,这是您无法确定的.

所以简而言之,不,字符串不应该是Unicode.文字应该是.但是YMMV.

特别:

  1. 这里不需要使用Unicode.您知道该字符串是否为ASCII.

  2. 取决于您是否需要将这些字符串与Unicode合并.

  3. 两种方式都有效.但是不要在需要时编码解码.解码ASAP,尽可能晚编码.使用编解码器可以很好地工作(或者从Python 2.7开始).

  4. 是啊.


Pau*_*ine 6

恕我直言(我的简单规则):

  1. 我应该这样做 print u'Some text' or just print 'Text'吗?

  2. 一切都应该是Unicode,这是否意味着,就像说我有一个元组: t = ('First', 'Second'), it should be t = (u'First', u'Second')

好吧,只有当我有一些高于ASCII 128的字符时才使用unicode文字:

   print 'New York', u'São Paulo'
   t = ('New York', u'São Paulo')
Run Code Online (Sandbox Code Playgroud)
  1. 在读/写文件时,我应该使用编解码器模块.对?或者我应该只使用标准方式或读/写和编码或解码所需的?

如果您期望unicode文本,请使用编解码器.

  1. 如果我从raw_input()获取字符串,我是否应该将其转换为Unicode?

仅当您期望可能转换到具有不同默认编码的另一个系统(包括数据库)的unicode文本时.

EDITED(关于混合unicode和字节串):

>>> print 'New York', 'to', u'São Paulo'
New York to São Paulo
>>> print 'New York' + ' to ' + u'São Paulo'
New York to São Paulo
>>> print "Côte d'Azur" + ' to ' + u'São Paulo'
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: 
     ordinal not in range(128)
>>> print "Côte d'Azur".decode('utf-8') + ' to ' + u'São Paulo'
Côte d'Azur to São Paulo
Run Code Online (Sandbox Code Playgroud)

因此,如果将包含utf-8(或其他非ascii char)的字节字符串与unicode文本混合而不进行显式转换,则会遇到问题,因为默认值为ascii.另一种方式似乎是安全的.如果遵循将包含非ascii的每个字符串写为unicode文字的规则,那么你应该没问题.

免责声明:我住在巴西,人们会说葡萄牙语,这是一种含有大量非ascii字符的语言.我的默认编码始终设置为'utf-8'.您的里程可能因英语/ ascii系统而异.