Python Unicode字符串格式化中的一个陷阱
Nov 07, 2016 am 10:14 AM今天帮同事研究一个莫名其妙的UnicodeDecodeError时发现了Python字符串格式化中的一个小陷阱,在此记录一下。原本的代码过于复杂,有太多与问题无关的东西,所以我在ipython里简单试验复现了问题,过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
看到In [7]之后的那个很怪异的UnicodeDecodeError没?它和上一句的唯一区别是’hello world‘变成了一个unicode对象而非str对象。但问题是,’hello world’只是单纯的英文字符串,不包含任何ASCII之外的字符,怎么会无法decode呢?再仔细看看异常附带的message,里面提到了0xe4,这个显然不是’hello world‘里面的,所以只能怀疑那句中文了,In [8]把它的字节序列打印了出来,果然就是它,第一个就是0xe4。
看来在字符串格式化的时候Python试图将a decode成unicode对象,并且decode时用的还是默认的ASCII编码而非实际的UTF-8编码。那这又是怎么回事呢??下面继续我们的试验:
1 2 3 4 |
|
仔细看,In [9]中的’hello’是普通的字符串,结果也是字符串(str对象),而In [10]中的’hello’变成了unicode对象,格式化的结果也变成unicode了(注意结果开头的那个u)。
所以真相是这样的:Python在格式化字符串的时候有一些隐藏着的小动作:如果%s对应的参数里有unicode,那么最终的结果也是unicode。在这种情况下模版字符串以及所有的%s参数中的str都会被decode成unicode,然而这个decode是隐式的,用户无法指定其使用的charset,Python只能用默认的ASCII。如果正好里面有非ASCII编码的字符串,就完蛋了……
看看Python文档怎么说的:
1 |
|
如果代码里混合着str和unicode,这种问题很容易出现。在同事的代码里,中文字符串是用户输入的,经过了正确的编码处理,是以UTF-8编码的str对象;但那个惹事的unicode对象,虽然其内容都是ASCII码,但其来源是sqlite3数据库查询的结果,而sqlite的API返回的字符串都是unicode对象,所以导致了这么怪异的结果。
Python 2的str和unicode真的挺坑爹,已经被它们害过好几次了。Python 3在这方面很有提升,期待它的全面普及!

Artikel Panas

Alat panas Tag

Artikel Panas

Tag artikel panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Apakah kelebihan dan kekurangan templat?

Google AI mengumumkan Gemini 1.5 Pro dan Gemma 2 untuk pembangun

Dengan hanya $250, pengarah teknikal Hugging Face mengajar anda cara memperhalusi Llama 3

Kongsi beberapa rangka kerja projek berkaitan AI dan LLM sumber terbuka .NET

Panduan lengkap untuk penyahpepijatan dan analisis fungsi golang

Bagaimana anda bertanya kepadanya Deepseek

Bagaimana untuk menyimpan fungsi menilai
