终于搞懂了python2的编码

在python2下碰到非常多次的中文乱码,这次来梳理一下编码问题。

在python 2中默认编码是 ASCII,而在python 3中默认编码是 unicode。

unicode是中间编码,任何字符编码之前的转换都必须解码成unicode,再编码成目标字符编码

在python2读取文件时,如果文件编码是utf-8的,那么中文读取出来前面是带u的,即是unicode编码。

python2编码转换

参考文章开头的图,任何编码转换之前都要解码成unicode,再转换到目标编码。

字节串-->decode('原来的字符编码')-->Unicode字符串-->encode('新的字符编码')-->字节串

# -*- coding: utf-8 -*-
utf_8_a = '中文'
gbk_a = utf_8_a.decode('utf-8').encode('gbk')
print(gbk_a.decode('gbk')) #输出结果: 中文

在python2中,如果碰到decode为原来的字符编码出错,检查一下你真实的文件编码是否与文件头一致。

python3字符编码

python 3的编码默认是unicode,所以字符编码之间的转换不需要decode过程,直接encode即可

注:在python 3,encode编码的同时会把stringl变成bytes类型,decode解码的同时会把bytes类型变成string类型

如何明显的区分unicode及byte,string

print type(xx)

unicode:

>>> unicode('中文','gbk')
u'\u4e2d\u6587'

byte:

b开头的

python2文件头的UTF-8或GBK会影响乱码

以python2举个例子,当文件编码头是GBK时,在py脚本中住csv中直接写入中文或者打印中文都是没有问题的。

可是当把文件的编码头改成UTF-8时,所有涉及中文的地方都要加上u前缀,否则打印会报错,写入到文件中的会是乱码

报错信息:

  File "E:\Code\km\km\km\get_all_none_meta.py", line 70, in main
print '获取完所有无meta的md文件共{}个,结果保存在:{}'.format(len(md_filelist),csv_file_fullpath)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u65e0' in position 11: ordinal not in range(128)

UTF-8下乱码修正:

print '获取完所有无meta的md文件共{}个,结果保存在:{}'.format(len(md_filelist),csv_file_fullpath)
#在UTF-8下要给所有可能会出现中文的字符串前都加上u
print u'获取完所有无meta的md文件共{}个,结果保存在:{}'.format(len(md_filelist),csv_file_fullpath)

python2中字符串前加u有什么作用

在 Python2 中,字符串前面加 u 表示这是一个 Unicode 字符串,即该字符串中可以包含任意 Unicode 字符,而不仅仅是 ASCII 字符集中的字符。如果没有使用 u,那么默认字符串是由 ASCII 字符集组成的,无法包含非 ASCII 字符。

例如,使用 u 前缀可以将带有中文字符的字符串表示为 Unicode 字符串:

u_str = u'这是一个 Unicode 字符串'

如果没有使用 u,则需要使用转义序列来表示中文字符:

str = '\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\x80\xe4\xb8\xaa Unicode \xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2'

需要注意的是,Python3 中所有的字符串都是 Unicode 字符串,因此不需要在字符串前面加 u。

python2简易处理中文

在一些python2的单文件的小工具中比较简单的处理中文,即不用在字符串前加u转成unicode,我的一个经验是:

把文件编码头改为GBK、GB18030,就不用特殊处理中文了,但会碰到中文在pycharame控制中打印出来是乱码,而在vscode中是好的。

# -*- coding: utf-8 -*-
print ('这是一段中文')#=>这是一段中文

更换编码

# -*- coding: GB18030 -*-
print ('这是一段中文')#=>����һ������

直接运行py文件,中文输出是正常的,可以知道是pycharm的控制台编码设置为了UTF-8

调整sys.setdefaultencoding,没用,因为这是python虚拟机的。

在pycharm中修改全局的编码,没用,也可能是我用的社区版有bug

有这几种方法:

  1. 在打印log的前面加上u
  2. 在vscode中运行

最后,为了让兼容性更好地运行在python2及python3中,建议统一使用utf-8编码

python2和python3

  • 【中文】这两字GBK编码:\xd6\xd0\xce\xc4

在python2下可以直接打印gbk编码,而python3是不行

Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:19:08) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print ('\xd6\xd0\xce\xc4')
中文

从上面的输出也验证这者是等价的:\xd6\xd0\xce\xc4 == 中文

python3

python3的输出如下:

Python 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print('\xd6\xd0\xce\xc4')
ÖÐÎÄ
>>> str1 = '中文'.encode('utf8')
>>> str1
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print (str1.decode('utf8'))
中文 >>> print (str1.decode('gbk'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 2: illegal multibyte sequence
#decode类型不匹配,所以出错

python dict打印出来是编码

如果要显示中文,建议用字符串拼接,而不要用dict。

t={1:"中",2:"hi"} #打印结果 {1: '\xe4\xb8\xad', 2: 'hi'}
t2={1:"china",2:"hi"} #打印结果:{1:"china",2:"hi"}

参考资料

Python基础【day03】:字符转编码操作(五) - 活的潇洒80 - 博客园 (cnblogs.com)

Python中的字符串与字符编码 - 帅丶高高 - 博客园 (cnblogs.com)

终于搞懂了python2和python3的encode(编码)与decode(解码)的更多相关文章

  1. 终于搞懂了vue 的 render 函数(一) -_-|||

    终于搞懂了vue 的 render 函数(一) -_-|||:https://blog.csdn.net/sansan_7957/article/details/83014838 render: h ...

  2. python2和python3中的编码问题

    开始拾起python,准备使用python3, 造轮子的过程中遇到了编码的问题,又看了一下python3和python2相比变化的部分. 首先说个概念: unicode:在本文中表示用4byte表示的 ...

  3. Python2和Python3的字符串编码和类型

    一.字符串编码和类型 任何编码格式的字符串,都可以和Unicode互相转换. gbk -> utf8 # 将字符串按指定格式进行解码,返回Unicode字符串unicode_str = gbk_ ...

  4. [转]我花了一个五一终于搞懂了OpenLDAP

    轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP)是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的 ...

  5. 探索JAVA并发 - 终于搞懂了sleep/wait/notify/notifyAll

    > sleep/wait/notify/notifyAll分别有什么作用?它们的区别是什么?wait时为什么要放在循环里而不能直接用if? ## 简介 首先对几个相关的方法做个简单解释,Obje ...

  6. 终于搞懂了PR曲线

    PR(Precision Recall)曲线 问题 最近项目中遇到一个比较有意思的问题, 如下所示为: 图中的PR曲线很奇怪, 左边从1突然变到0. PR源码分析 为了搞清楚这个问题, 对源码进行了分 ...

  7. hdu1711(终于搞懂了KMP算法了。。)

    题意:给你两个长度分别为n(1 <= N <= 1000000)和m(1 <= M <= 10000)的序列a[]和b[],求b[]序列在a[]序列中出现的首位置.如果没有请输 ...

  8. Lua的闭包详解(终于搞懂了)

    词法定界:当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征叫做词法定界 table.sort(names,functin (n1,n2) return grades[n1] ...

  9. 终于搞懂了shell bash cmd...

    问题一:DOS与windows中cmd区别 在windows系统中,“开始-运行-cmd”可以打开“cmd.exe”,进行命令行操作. 操作系统可以分成核心(kernel)和Shell(外壳)两部分, ...

  10. IntelliJ IDEA 部署 Web 项目,终于搞懂了!

    这篇牛逼: IDEA 中最重要的各种设置项,就是这个 Project Structre 了,关乎你的项目运行,缺胳膊少腿都不行. 最近公司正好也是用之前自己比较熟悉的IDEA而不是Eclipse,为了 ...

随机推荐

  1. 项目打包后配置到node服务器

    1.将项目进行打包 npm run build项目根目录下会多出一个打包好的由.js .html .css文件组成的dist文件夹,如图 2.搭建node微型服务器   新建文件夹命名"no ...

  2. 2023-01-10:智能机器人要坐专用电梯把货物送到指定地点, 整栋楼只有一部电梯,并且由于容量限制智能机器人只能放下一件货物, 给定K个货物,每个货物都有所在楼层(from)和目的楼层(to),

    2023-01-10:智能机器人要坐专用电梯把货物送到指定地点, 整栋楼只有一部电梯,并且由于容量限制智能机器人只能放下一件货物, 给定K个货物,每个货物都有所在楼层(from)和目的楼层(to), ...

  3. 2021-06-30:给定长度为m的字符串aim,以及一个长度为n的字符串str ,问能否在str中找到一个长度为m的连续子串, 使得这个子串刚好由aim的m个字符组成,顺序无所谓, 返回任意满足条件

    2021-06-30:给定长度为m的字符串aim,以及一个长度为n的字符串str ,问能否在str中找到一个长度为m的连续子串, 使得这个子串刚好由aim的m个字符组成,顺序无所谓, 返回任意满足条件 ...

  4. 提升 Apache Hudi Upsert 性能的三个建议

    Apache Hudi 社区一直在快速发展,各公司正在寻找方法来利用其强大的功能来有效地摄取和管理大规模数据集. 每周社区都会收到一些常见问题,最常见的问题与 Hudi 如何执行更新插入有关,以确保以 ...

  5. GIT多场景下使用

    git对于大家应该都不太陌生,熟练使用git已经成为程序员的一项基本技能,尽管在工作中有诸如 Sourcetree这样牛X的客户端工具,使得合并代码变的很方便.但找工作面试和一些需彰显个人实力的场景, ...

  6. Pycharm激活码,Pycharm稳定专属激活码(持续更新)

    分享一下 PyCharm 2023.1.2 最新激活注册码,破解教程如下,可免费永久激活,亲测有效,下面是详细文档哦~ 申明:本教程 PyCharm 激活码收集于网络,请勿商用,仅供个人学习使用,如有 ...

  7. hexrays sdk study

    There are 20 examples in /ida_path/plugins/hexrays_sdk/plugins, you can learn from that, you can als ...

  8. 杭电多校第二场 DOS Card

    杭电多校第二场 DOS Card 评价一下这道题:我写过最爽的线段树题. 这道题真的非常令人身心愉悦,非常厉害的一道线段树入门题.我写这个一次调试都没有,过了样例就交了就过了,一切都是行云流水. 这道 ...

  9. R 包 optparse 之命令行参数传递

    对于经常与 Linux 打交道的生物信息分析童鞋们,我们今天分享一下怎么在命令行下通过传递参数(类似perl.python) 的方式执行 R 脚本. 一般来说,命令行下使用 Rscript 执行 R ...

  10. 通过redis学网络(1)-用go基于epoll实现最简单网络通信框架

    本系列主要是为了对redis的网络模型进行学习,我会用golang实现一个reactor网络模型,并实现对redis协议的解析. 系列源码已经上传github https://github.com/H ...