Python unicode and bytestring revisit
Unicode
- unicode的字符集几乎包含了世界上所有文字,它用code point来表示每一个字符
- utf8 encoding是一种unicode的编码方法
- utf8使用1-4个字节来存储unicode字符,utf16使用2-4个字节,而utf32使用定长的4个字节
Bytestring
在Python中用单引号,双引号或者三引号括起来的字符都是str(确切地说是str的string literal),它们的实际值,在不同的系统不尽相同(ASCII码例外)。
在windows下
1 2 3 4 5 6 7 |
|
而在ubuntu下
1 2 3 4 5 6 7 |
|
可见,对于str,Python使用了系统的默认编码(而不是Python默认的ascii编码)进行编码
Confusion
Why u”你好” works while “你好” doesn’t?
1 2 3 4 5 6 7 |
|
首先,对于encode操作,错误里报”..can’t decode..“,这个追过代码没追到,在Stackoverflow上提问,有同学帮忙解决了,看这里。
其次,对于为什么同是对literal进行encode, unicode literal就不会报错呢。
在What’s New In Python 3.0找到了答案:
The biggest difference with the 2.x situation is that any attempt to mix text and data in Python 3.0 raises TypeError, whereas if you were to mix Unicode and 8-bit strings in Python 2.x, it would work if the 8-bit string happened to contain only 7-bit (ASCII) bytes, but you would get UnicodeDecodeError if it contained non-ASCII values. This value-specific behavior has caused numerous sad faces over the years.
这么说来还是Python 2.X自身的问题了。在2.X的版本中,string和bytes使用的数据类型都是str,所以str既是字面值(literal),也是二进制值(binary)。
1 2 |
|
而且很容易造成混淆的是ASCII码的字面值和二进制值都是用字面值表示
1 2 |
|
这对于ASCII码来说无所谓,但如果str包含了非ASCII码的字符,在encode的时候就会报上述错。而在Py3k中,这两者被区分开了
Python 3.0 uses the concepts of text and (binary) data instead of Unicode strings and 8-bit strings. All text is Unicode; however encoded Unicode is represented as binary data. The type used to hold text is str, the type used to hold data is bytes.
You can no longer use u”…“ literals for Unicode text. However, you must use b”…“ literals for binary data.
在Py3k下运行的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
在Django的字符串处理中,Django假设所有的str都使用了UTF8编码,如果在某些涉及到中文的地方使用了str就很容易造成错误,所以在使用字符串这种类型的时候,最好统一使用unicode。
最后,可以通过更改解释器的默认编码来避免上述问题,当然这种做法已经deprecated了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|