python字符串编码及乱码解决方案

python字符串编码及乱码解决方案http://blog.csdn.net/pipisorry/article/details/44136297字符编码详解[字符编码ASCII,Unicode和UTF-8]主要非英文字符集的编码范围范围 编码 说明 2E80~33FFh 中日韩符号区 收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符, 中日韩的符号、标点、带…

大家好,又见面了,我是你们的朋友全栈君。

http://blog.csdn.net/pipisorry/article/details/44136297

字符编码详解

[字符编码ASCII,Unicode和UTF-8]

主要非英文字符集的编码范围

范围 编码 说明
2E80~33FFh 中日韩符号区

收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符,

中日韩的符号、标点、带圈或带括符文数字、月份,

以及日本的假名组合、单位、年号、月份、日期、时间等。

3400~4DFFh 中日韩认同文字扩充A区 中日韩认同表意文字扩充A区,总计收容6,582个中日韩汉字。
4E00~9FFFh 中日韩认同表意文字区 中日韩认同表意文字区,总计收容20,902个中日韩汉字。
A000~A4FFh 彝族文字区 收容中国南方彝族文字和字根
AC00~D7FFh 韩文拼音组合字区 收容以韩文音符拼成的文字
F900~FAFFh 中日韩兼容表意文字区 总计收容302个中日韩汉字
FB00~FFFDh 文字表现形式区

收容组合拉丁文字、希伯来文、阿拉伯文、中日韩直式标点、小符号、

半角符号、全角符号等。

       匹配所有中日韩非符号字符,那么正则表达式应该是^[\u2E80-\u9FFF]+$, 包括我們臺灣省還在盲目使用的繁體中文。中文的正则表达式, 应该是^[\u4E00-\u9FFF]+$, 需要注意的是^[\u4E00-\u9FA5]+$这是专门用于匹配简体中文的正则表达式, 实际上繁体字也在里面, 也通过了, 当然, ^[\u4E00-\u9FFF]+$也是一样的结果。

皮皮Blog

 

Python源码的编码方式

str与字节码

s = "人生苦短"

        s是个字符串,它本身存储的就是字节码(这个s定义在文件中的一行,或者命令行中的一行)。那么这个字节码是什么格式的?

        如果这段代码是在解释器上输入的,那么这个s的格式就是解释器的编码格式,对于windows的cmd而言,就是gbk。

        如果将段代码是保存后才执行的,比如存储为utf-8,那么在解释器载入这段程序的时候,就会将s初始化为utf-8编码。

unicode与str

        我们知道unicode是一种编码标准,具体的实现标准可能是utf-8,utf-16,gbk ……

        python 在内部使用两个字节来存储一个unicode,使用unicode对象而不是str的好处,就是unicode方便于跨平台。

        你可以用如下两种方式定义一个unicode:(在python2中)

1 s1 = u"人生苦短"
2 s2 = unicode("人生苦短", "utf-8")

python3

        字符串实际就是用的unicode,直接s = “人生苦短”

        Note: py3定义bytes使用sb = b’dfja’

python 2.x和3.x中的字符串编码区别

python字符串编码及乱码解决方案

        2.x中字符串有str和unicode两种类型,str有各种编码区别,unicode是没有编码的标准形式。unicode通过编码转化成str,str通过解码转化成unicode。

        3.x中将字符串和字节序列做了区别,字符串str是字符串标准形式与2.x中unicode类似,bytes类似2.x中的str有各种编码区别。bytes通过解码转化成str,str通过编码转化成bytes。

        2.x中可以查看unicode字节序列,3.x中不能。

Python 2:Python 2的源码.py文件默认的编码方式为ASCII

        如果想使用一种不同的编码方式来保存Python代码,我们可以在每个文件的第一行放置编码声明(encoding declaration)。

        以下声明定义.py文件使用windows-1252编码方式:# -*- coding: windows-1252 -*-

        Note: 1. 从技术上说,字符编码的重载声明也可以放在第二行,如果第一行被类UNIX系统中的hash-bang命令占用了。

                2. 了解更多信息,请参阅PEP263: 指定Python源码的编码方式。

Python 3:Python 3的源码.py文件 的默认编码方式为UTF-8

Python 3.x中的Unicode

        在Python 3.0之后的版本中,所有的字符串都是使用Unicode编码的字符串序列,同时还有以下几个改进:

1、默认编码格式改为unicode

2、所有的Python内置模块都支持unicode

3、不再支持u中文的语法格式

        所以,对于Python 3.x来说,编码问题已经不再是个大的问题,基本上很少遇到编码异常。

        在Python 3,所有的字符串都是使用Unicode编码的字符序列。不再存在以UTF-8或者CP-1252编码的情况。也就是说,这个字符串是以UTF-8编码的吗?不再是一个有效问题。UTF-8是一种将字符编码成字节序列的方式。如果需要将字符串转换成特定编码的字节序列,Python 3可以为你做到。如果需要将一个字节序列转换成字符串,Python 3也能为你做到。字节即字节,并非字符。字符在计算机内只是一种抽象。字符串则是一种抽象的序列。

>>> s = "深入 Python"
>>> len(s)
9
>>> s[0]
"深"
>>> s + " 3"
"深入 Python 3"s = "深入 Python"
>>> len(s)
9
>>> s[0]
"深"
>>> s + " 3"
"深入 Python 3"
  1. Python中,字符串可以想像成由字符组成的元组。

  2. Just like getting individual items out of a list, you can get individual characters out of a string using index notation.
    与取得列表中的元素一样,也可以通过下标记号取得字符串中的某个字符。

文件头声明编码

关于python文件头部分知识的讲解

顶部的:# -*- coding: utf-8 -*-或者# coding: utf-8目前有三个作用

  1. 如果代码中有中文注释,就需要此声明。
  2. 比较高级的编辑器(比如我的emacs),会根据头部声明,将此作为代码文件的格式。
  3. 程序会通过头部声明,解码初始化 u”人生苦短”,这样的unicode对象,(所以头部声明和代码的存储格式要一致)。

Example2

url编码

        通过urllib.parse.quote 将字节序列转化成url的中文编码形式,逆过程是unquote函数。

  1. >>> import urllib.parse  

  2. >>> res = urllib.parse.quote(utfs)  

  3. >>> res  

  4. ‘%E5%8C%97%E4%BA%AC%E5%B8%82’

皮皮Blog

 

 

Python编码错误及解决方法

        字符串是Python中最常用的数据类型,而且很多时候你会用到一些不属于标准ASCII字符集的字符,这时候代码就很可能抛出UnicodeDecodeError: ascii codec cant decode byte 0xc4 in position 10: ordinal not in range(128)异常。这种异常在Python中很容易遇到,尤其是在Python2.x中。

        字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。但是,Python 2.x的默认编码格式是ASCII,就是说,在没有指定  Python源码编码格式的情况下,源码中的所有字符都会被默认为ASCII码。也因为这个根本原因,在Python 2.x中经常会遇UnicodeDecodeError或者UnicodeEncodeError的异常。

Unicode为了能够处理Unicode数据,同时兼容Python某些内部模块,Python 2.x中提供了Unicode这种数据类型,通过decode和encode方法可以将其它编码和Unicode编码相互转化,但同时也引入了UnicodeDecodeError和UnicodeEncodeError异常。

python编码异常解决原则

1、终极原则:遵循PEP0263原则,声明编码格式 且 decode early, unicode everywhere, encode late

首先需要在文件头部声明编码:# -*- coding: <encoding name> -*-

在PEP 0263 Defining Python Source Code Encodings中提出了对Python编码问题的最基本的解决方法:在Python源码文件中声明编码格式,最常见的声明方式如下:

#!/usr/bin/python

# -*- coding: <encoding name> -*-

Note:其中<encoding name>是代码所需要的编码格式,它可以是任意一种Python支持的格式,一般都会使用utf-8的编码格式。# -*- coding: utf-8 -*-是Python文件声明,意思是:当前.py文件中所有的字符串是utf-8编码的,所以文件中的字符需要使用utf-8解码成unicode!

decode early, unicode everywhere, encode late

        在输入或者声明字符串的时候,尽早地使用decode方法将字符串转化成unicode编码格式(当然除了本身就是unicode的字符);然后在程序内统一使用unicode格式进行处理,比如字符串拼接、字符串替换、获取字符串的长度、正则表达式等操作;最后,在return、输出字符串的时候(控制台/网页/文件),通过encode方法将字符串转化为你所想要的编码格式/输入时的编码格式。按照这个原则处理Python的字符串,基本上可以解决所有的编码问题。

获取字符串编码:

        input_encoding = 'utf-8'
        encodings = ['ascii', 'utf-8', 'gb2312', 'windows-1250', 'windows-1252']
        for e in encodings:
            try:
                source = source.decode(e)
                group_patterns = [g.decode(e) for g in group_patterns]
            except UnicodeDecodeError:
                continue
            else:
                print('str encoding:  %s ' % e)
                input_encoding = e
                break

或者安装chardet库

        import chardet
        input_encoding = chardet.detect(source)['encoding']
        source = source.decode(chardet.detect(source)['encoding'])
        group_patterns = [g.decode(chardet.detect(g)['encoding']) for g in group_patterns]

 但是这个库有时候识别会出错(毕竟是概率算法),如下面识别不了gbk:

print(chardet.detect(u'黑头'.encode('gbk'))['encoding'])
print(u'黑头'.encode('gbk').decode(chardet.detect(u'黑头'.encode('gbk'))['encoding']).encode('gbk'))

输出KOI8-R
�l�٧ިi

        另外还应该使用codecs模块打开文件,内置的open函数打开文件时,read方法读取的是一个str(私以为叫做字节数组更合适),如果读取的是其它编码的文字,则需要decode之后再做使用。

屏幕快照 2016-03-01 16.54.33.png

        对于使用open函数打开文件之后的写操作(多字节编码的字符串),则需要将需要写入的字符串按照其编码encode为一个str,如果直接写入,则会引发如下错误(如果在代码中加入了encoding声明,则会按照声明的编码格式encode后写入):

        除此以外,codecs模块也提供了一个open函数,可以直接指定好编码打开一个文本文件,那么读取到的文件内容则直接是一个unicode字符串。对应的指定编码后的写入文件,则可以直接将unicode写到文件中。通过codecs.open可以避免很多编码问题:

屏幕快照 2016-03-01 17.02.53.png

 

2、Reset默认编码

python中设置默认编码defaultencoding。Python中出现这么多编码问题的根本原因是Python 2.x的默认编码格式是ASCII,是许多错误的原因,所以你也可以通过以下的方式修改默认的编码格式:

import sys

sys.setdefaultencoding(utf-8)

如果你在python中进行编码和解码的时候,不指定编码方式,那么python就会使用defaultencoding。比如将str编码为另一种格式,就会使用defaultencoding。

s.encode("utf-8") 等价于 s.decode(defaultencoding).encode("utf-8")

Note: 这个过程是s先通过defaultencoding解码为unicode,再编码为utf-8类型的编码。

再比如你使用str创建unicode对象时,如果不说明这个str的编码格式,那么程序也会使用defaultencoding。

u = unicode("人生苦短") 等价于 u = unicode("人生苦短",defaultencoding)

Note: 可以解决部分编码问题,但是同时也可能引入很多其他问题。

3、使用u中文替代中文(py2)

str1 = ‘中文编码’

str2 = u’中文编码’

Python中有以上两种声明字符串变量的方式,它们的主要区别是编码格式的不同,其中,str1的编码格式和Python文件声明的编码格式一致,而str2的编码格式则是Unicode。如果你要声明的字符串变量中存在非ASCII的字符,那么最好使用str2的声明格式,这样你就可以不需要执行decode,直接对字符串进行操作,可以避免一些出现异常的情况。

Note: python3不支持u的声明方式。

4、升级Python 2.x到3.x

主要是因为Python 2.x的编码设计问题。当然,升级到Python 3.x肯定可以解决大部分因为编码产生的异常问题。毕竟Python 3.x版本对字符串这部分还是做了相当大的改进的。

原因参见前面关于python2.x和3.x的区别。

 

 

常见编码异常

常见编码异常

        Python中常见的几种编码异常有SyntaxError: Non-ASCII character、UnicodeDecodeError和UnicodeEncodeError等(几乎都只存在于python2中)。 python3基本没有编码异常,只要在头部声明# -*- coding: utf-8 -*-,python源代码中的字符就是utf-8,不需要decode encode。

1、SyntaxError: Non-ASCII character

        这种异常主要原因是Python源码文件中有非ASCII字符,而且同时没有声明源码编码格式,例如:

        s = ‘中文’

        print s

        # 抛出异常

        解决: 文件头部声明编码# -*- coding: utf-8 -*-

        Python2中,如果在源码首行(或在指定sha-bang时的第二行)不显式指定编码,则无法在源码中出现非ASCII字符。这是由于Python2解释器默认将源码认作ASCII编码格式。[PEP263]

2、UnicodeDecodeError

        这个异常有时候会在调用decode方法时出现,原因是Python打算将其他编码的字符转化为Unicode编码,但是字符本身的编码格式和decode方法传入的编码格式不一致,例如:

        #!/usr/bin/python

        # -*- coding: utf-8 -*-

        s = ‘中文’

        s.decode(‘gb2312’)

        #UnicodeDecodeError: gb2312 codec cant decode bytes in position 2-3: illegal multibyte sequenceprint s

Note:上面这段代码中字符串s的编码格式是utf-8(# -*- coding: utf-8 -*-声明的意思是:当前.py文件中所有的字符串是utf-8编码的),但是在使用decode方法转化为Unicode编码时传入的参数是‘gb2312’,因此在转化的时候抛出UnicodeDecodeError异常。

        还有一种情况是在encode的时候:

        #!/usr/bin/python

        # -*- coding: utf-8 -*-

        s = ‘中文’

        s.encode(‘gb2312’)

        # UnicodeDecodeError: ascii codec cant decode byte 0xe4 in position 0: ordinal not in range(128)print s

Note:这里的s是utf-8编码的,直接使用s.encode(gb2312)实际使用了系统默认defalutencoding(ascii)来解码,等价于s.decode(defaultencoding).encode(gb2312),而s的实际编码与defaultencoding不同。

3、UnicodeEncodeError

        错误的使用decode和encode方法会出现这种异常,比如:使用decode方法将Unicode字符串转化的时候。比如下面s是unicode(所以不需要再decode,而是应该encode成utf-8)。

        #!/usr/bin/python

        # -*- coding: utf-8 -*-

        s = u’中文’

        s.decode(‘utf-8’)

        #UnicodeEncodeError: ascii codec cant encode characters in position 0-1: ordinal not in range(128)print s

print输出异常

       有一种情况还是会出现编码异常,就是使用print()时:

        print(测试)

        UnicodeEncodeError: ‘ascii’ codec can’t encode character ‘\uff1a’ in position **: ordinal not in range(128)

        出现这个错误的原因是因为print系统有它自己的编码,在一般python(2/3)环境中,输出时会将Unicode转化为utf-8,但是也可能是转化为ascii,这时如果unidoce中有中文就会出错。如果直接输出unicode字符串,编译器会自动encode输出为默认编码,但是如果是字符串列表是什么就输出什么不会处理编码,所以unicode最好还是自定义encode之后再输出。

        还有一种是,如果encode(‘gbk’),但是文件头# -*- coding:utf-8 -*-输出也会乱码。输出时不能使用print(pattern.encode(‘utf-8’), group.encode(‘utf-8’)),而应该分开print,否则还是乱码但是不报错。

        标准输出的定义如下: sys.stdout = codecs.getwriter(“utf-8”)(sys.stdout.detach())

        查看输出编码:

print(sys.stdout) #或者sys.stdout.encoding
<_io.TextIOWrapper name='<stdout>' encoding='ANSI_X3.4-1968'>竟然不是utf-8!

        解决:

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
#或者 sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
print(sys.stdout)
<_io.TextIOWrapper name='<stdout>' encoding='utf-8'>

        或者运行python的时候加上PYTHONIOENCODING=utf-8,即PYTHONIOENCODING=utf-8 python your_script.py

这时就能正确输出中文了。

python2输出示例

# -*- coding:utf-8 -*-
s = "人生苦短"  # su是一个utf-8格式的字节串
u = s.decode("utf-8")  # s被解码为unicode对象,赋给u
sg = u.encode("utf-8")  # u被编码为gbk格式的字节串,赋给sg
print u
print sg

输出都是

人生苦短
人生苦短       

python3输出示例

>>> ss = ‘北京市’  
>>> type(ss)  
<class ‘str’>  
>>> us = ss.encode(‘gbk’)  
>>> type(us)  
<class ‘bytes’>  
>>> us  
b’\xb1\xb1\xbe\xa9\xca\xd0′  
>>> utfs = ss.encode(‘utf-8’)  
>>> print(utfs)  
b’\xe5\x8c\x97\xe4\xba\xac\xe5\xb8\x82′  
>>> type(utfs)  
<class ‘bytes’>  
>>> xx = utfs.decode(‘utf-8’)  
>>> type(xx)  
<class ‘str’>  
>>> print(xx)  
北京市  

        encode后的bytes直接输出是这种形式b’\xe5\x8c\x97\xe4\xba\xac\xe5\xb8\x82′  ,需要decode成python3的str才可见中文。

更复杂示例

1 s = "人生苦短"
2 s.encode('gbk')

        看!str也能编码,(事实上unicode对象也能解码,但是意义不大)

Note:原理,当对str进行编码时,会先用默认编码将自己解码为unicode,然后在将unicode编码为你指定编码。

这就引出了python2.x中在处理中文时,大多数出现错误的原因所在:python的默认编码,defaultencoding是ascii

看这个例子

1 # -*- coding: utf-8 -*-
2 s = "人生苦短"
3 s.encode('gbk')

        上面的代码会报错,错误信息:UnicodeDecodeError: 'ascii' codec can't decode byte ......

        因为你没有指定defaultencoding,所以它其实在做这样的事情:

1 # -*- coding: utf-8 -*-
2 s = "人生苦短"
3 s.decode('ascii').encode('gbk')

python读取文件编码错误出现乱码

        首先用notepad++等文本查看器查看读取文件的编码,如文件编码为utf-8则使用utf-8编码方式打开{其它格式还有gbk, gb2312,ansi等等}

file = open(filename, encoding='UTF-8')

        基本没有编码错误,还是出现某几个字符错误也可以用‘ignore’忽略掉

file = open(filename, encoding='UTF-8', errors='ignore')

[java中文乱码解决之道]

python读取文件BOM字符处理

        在windows上使用open打开utf-8编码的txt文件时开头会有一个多余的字符\ufeff,它叫BOM,是用来声明编码等信息的,但python会把它当作文本解析。

        对UTF-16, Python将BOM解码为空字串。然而对UTF-8, BOM被解码为一个字符\ufeff。

        如何去掉bom字符?

        解决修改encoding为utf-8_sig或者utf_8_sig

        open(‘1.txt’, encoding=’utf_8_sig’ )

[python 的字符编码和中文处理]

[带 BOM 的 UTF-8」和「无 BOM 的 UTF-8」有什么区别?网页代码一般使用哪个?]

from:http://blog.csdn.net/pipisorry/article/details/44136297

ref: python中的str与unicode处理方法

http://mp.weixin.qq.com/s?__biz=MjM5NzU0MzU0Nw==&mid=204655326&idx=1&sn=cbe436b2ecf1bb7f4f11992756d407c7&from=singlemessage&isappinstalled=0#rd

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134682.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(1)
blank

相关推荐

  • MySql数据库约束

    关系型数据库系统和文件系统的一个不同点是,关系数据库本身能保证存储数据的完整性,不需要应用程序的控制,而文件系统一般需要在程序端进行控制。当前几乎所有的关系型数据库都提供了约束(constraits)

    2021年12月28日
  • Python绘图库Matplotlib.pyplot之网格线设置(plt.grid())「建议收藏」

    Python绘图库Matplotlib.pyplot之网格线设置(plt.grid())「建议收藏」很多时候为了可视化效果的美观,就不得不从细节上下手,这里我们就介绍一下这些细节之一的网格线。首先导入需要用到的库,matplotlib.pyplot是必须的,Numpy是为了生成画布用的。importnumpyasnpimportmatplotlib.pyplotasplt生成网格plt.gcf().set_facecolor(np.ones(3)*240/…

  • 全面理解Java内存模型

    Java内存模型即JavaMemoryModel,简称JMM。JMM定义了Java虚拟机(JVM)在计算机内存(RAM)中的工作方式。JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的。如果我们要想深入了解Java并发编程,就要先理解好Java内存模型。Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步。原始的Java内存模型效率并不是很理想,因此Jav

  • 35岁以上的IT人士如果有一天被公司裁员了,该怎么办?

    35岁以上的IT人士如果有一天被公司裁员了,该怎么办?我觉得裁员和年龄无关,和本人的技能,工作态度,处事规则有关系。大家都知道华为裁员比例厉害,特别是对35岁以上的,会感到中年危机。但是我几个在华为的同学,都到了40岁了工作依然好好的,也没有见谁被裁掉。如果在工作中保持积极的态度,做事主动,平常多学习,和同事,领导的关系都不错,那么也不会被裁掉。作为已经到而立之年的中年人,给大家一点建议吧。在工作和生活中时刻保持乐观的心态,做事积极主动,多想多思考,与同事和领导友好相处,尽量让自己成为不可替代的人。那么你就不会被裁掉,也不会有中年危机。…

  • Odin Inspector 系列教程 — Dictionary Drawer Settings Attribute[通俗易懂]

    Odin Inspector 系列教程 — Dictionary Drawer Settings Attribute[通俗易懂]DictionaryDrawerSettings自定义字典绘制方式默认以左侧为key,右侧为value的形式展示,如果需要进行序列化,需要继承自SerializedMonoBehaviour[DictionaryDrawerSettings()][ShowInInspector][InfoBox(“为了序列化字典,我们需要做…

  • python ip池(python 连接池)

    ,都说标题是文章的灵魂,想了半天没想到什么比较有创意的标题,只好拿一个去年的爆款标题套一下。啊哈哈哈哈哈哈,朕真是太机智了这是一篇介绍如何使用python搭建IP池的文章,如果爱卿对此不感兴趣,那很抱歉,标题耽误了你宝贵的时间。事情的起因是这样,前段时间我写了一篇介绍如何爬取小说的blog【python那些事.No2】,在爬取的过程中,发现同一个IP连续只能获取前几页小说内容,原本是想搭建…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号