1 python编码基础

对应 C/C++ 的 char 和 wchar_t, Python 也有两种字符串类型,str 与 unicode:

str与unicode

 1 # -*- coding: utf-8 -*-
 2 # file: example1.py
 3 import string
 4
 5 # 这个是 str 的字符串
 6 s = '关关雎鸠'
 7
 8 # 这个是 unicode 的字符串
 9 u = u'关关雎鸠'
10
11 print isinstance(s, str)      # True
12 print isinstance(u, unicode)  # True
13
14 print s.__class__   # <type 'str'>
15 print u.__class__   # <type 'unicode'>stryu

前面的申明:# -*- coding: utf-8 -*- 表明,上面的 Python 代码由 utf-8 编码。
两个 Python 字符串类型间可以用 encode / decode 方法转换:

1 # 从 str 转换成 unicode
2 print s.decode('utf-8')   # 关关雎鸠
3
4 # 从 unicode 转换成 str
5 print u.encode('utf-8')   # 关关雎鸠

encode/decode转换

为什么从 unicode 转 str 是 encode,而反过来叫 decode?

因为 Python 认为 16 位的 unicode 才是字符的唯一内码,而大家常用的字符集如 gb2312,gb18030/gbk,utf-8,以及 ascii 都是字符的二进制(字节)编码形式。把字符从 unicode 转换成二进制编码,当然是要 encode。

反过来,在 Python 中出现的 str 都是用字符集编码的 ansi 字符串。Python 本身并不知道 str 的编码,需要由开发者指定正确的字符集 decode。

(补充一句,其实 Python 是可以知道 str 编码的。因为我们在代码前面申明了 # -*- coding: utf-8 -*-,这表明代码中的 str 都是用 utf-8 编码的,我不知道 Python 为什么不这样做。)
如果用错误的字符集来 encode/decode 会怎样?

设置编解码字符集

 1 # 用 ascii 编码含中文的 unicode 字符串
 2 u.encode('ascii')  # 错误,因为中文无法用 ascii 字符集编码
 3                    # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
 4
 5 # 用 gbk 编码含中文的 unicode 字符串
 6 u.encode('gbk')  # 正确,因为 '关关雎鸠' 可以用中文 gbk 字符集表示
 7                  # '\xb9\xd8\xb9\xd8\xf6\xc2\xf0\xaf'
 8                  # 直接 print 上面的 str 会显示乱码,修改环境变量为 zh_CN.GBK 可以看到结果是对的
 9
10 # 用 ascii 解码 utf-8 字符串
11 s.decode('ascii')  # 错误,中文 utf-8 字符无法用 ascii 解码
12                    # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
13
14 # 用 gbk 解码 utf-8 字符串
15 s.decode('gbk')  # 不出错,但是用 gbk 解码 utf-8 字符流的结果,显然只是乱码
16                  # u'\u934f\u51b2\u53e7\u95c6\u5ea8\设定

为什么 Python 这么容易出现字符串编/解码异常?

这要提到处理 Python 编码时容易遇到的两个陷阱。第一个是有关字符串连接的:

 1 # -*- coding: utf-8 -*-
 2 # file: example2.py
 3
 4 # 这个是 str 的字符串
 5 s = '关关雎鸠'
 6
 7 # 这个是 unicode 的字符串
 8 u = u'关关雎鸠'
 9
10 s + u  # 失败,UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

字符串连接

简单的字符串连接也会出现解码错误?

陷阱一:在进行同时包含 str 与 unicode 的运算时,Python 一律都把 str 转换成 unicode 再运算,当然,运算结果也都是 unicode。

由于 Python 事先并不知道 str 的编码,它只能使用 sys.getdefaultencoding() 编码去 decode。在我的印象里,sys.getdefaultencoding() 的值总是 'ascii' ——显然,如果需要转换的 str 有中文,一定会出现错误。

除了字符串连接,% 运算的结果也是一样的:

 1 # 正确,所有的字符串都是 str, 不需要 decode
 2 "中文:%s" % s   # 中文:关关雎鸠
 3
 4 # 失败,相当于运行:"中文:%s".decode('ascii') % u
 5 "中文:%s" % u  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)
 6
 7 # 正确,所有字符串都是 unicode, 不需要 decode
 8 u"中文:%s" % u   # 中文:关关雎鸠
 9
10 # 失败,相当于运行:u"中文:%s" % s.decode('ascii')
11 u"中文:%s" % s  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

%运算

其实,sys.getdefaultencoding() 的值是可以用“后门”方式修改的,我不是特别推荐这个解决方案,但是还是贴一下,因为后面有用:

 1 # -*- coding: utf-8 -*-
 2 # file: example3.py
 3 import sys
 4
 5 # 这个是 str 的字符串
 6 s = '关关雎鸠'
 7
 8 # 这个是 unicode 的字符串
 9 u = u'关关雎鸠'
10
11 # 使得 sys.getdefaultencoding() 的值为 'utf-8'
12 reload(sys)                      # reload 才能调用 setdefaultencoding 方法
13 sys.setdefaultencoding('utf-8')  # 设置 'utf-8'
14
15 # 没问题
16 s + u  # u'\u5173\u5173\u96ce\u9e20\u5173\u5173\u96ce\u9e20'
17
18 # 同样没问题
19 "中文:%s" % u   # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'
20
21 # 还是没问题
22 u"中文:%s" % s  # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'

setdefaultencoding

可以看到,问题魔术般的解决了。但是注意! sys.setdefaultencoding() 的效果是全局的,如果你的代码由几个不同编码的 Python 文件组成,用这种方法只是按下了葫芦浮起了瓢,让问题变得复杂。
另一个陷阱是有关标准输出的。(另一个陷阱跟本文章关系不大,请参考这一节的原文:http://in355hz.iteye.com/blog/1860787)

2 python读写ini配置文件

以上介绍了基础python编解码知识,下面具体说明ConfigParser如果管理ini配置文件
配置文件编码为UTF-8,内容如下:

1 [section]
2 option=中文字符串

cfg.ini

可以通过Notepad++来查看cfg.ini文件的编码方式

ConfigParser可以方便的读取ini配置文件,但是当重新写入时会遇到问题

 1 import codecs
 2 import ConfigParser
 3
 4 cfgfile="cfg.ini"
 5
 6 config = ConfigParser.ConfigParser()
 7 config.readfp(codecs.open(cfgfile, "r", "utf-8"))
 8 value = config.get("section","option")
 9 #config.write(open("cfg2.ini", "w+"))
10 config.write(codecs.open("cfg2.ini", "w+", "utf-8"))

write error

跟踪了一下,在ConfigParser模块的如下位置出现问题:

具体来说是str(value)出错了,因为在例子中的value值为“中文字符串”这已经超出ascii编码的处理范围,我的解决方法是重新实现写入操作,请参考代码:

 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 #-------------------------------------------------------------------------------
 4 # Name:
 5 # Purpose:
 6 #
 7 # Author:      ZWW
 8 #
 9 # Created:     19/01/2014
10 # Copyright:   (c) ZWW 2014
11 # Licence:     <your licence>
12 #-------------------------------------------------------------------------------
13 import codecs
14 import ConfigParser
15 import types
16 import sys
17
18 cfgfile="cfg.ini"
19
20 def ini_set(sec,key,value):
21     try:
22         config.readfp(codecs.open(cfgfile, "r", "utf-8"))
23         if not config.has_section(sec):
24             temp = config.add_section(sec)
25         config.set(sec, key, value)
26     except Exception as e:
27         print("error",str(e))
28     file = codecs.open(cfgfile, "w", "utf-8")
29     sections=config.sections()
30     for section in sections:
31         #print section
32         file.write("[%s]\n" % section)
33         for (key, value) in config.items(section):
34             if key == "__name__":
35                 continue
36             if type(value) in (type(u'') , type('')):
37                 file.write(key+"="+value)
38             elif type(value) == type(1):
39                 optStr="%s=%d"%(key,value)
40                 file.write(optStr)
41             elif type(value) == type(1.5):
42                 optStr="%s=%f"%(key,value)
43                 file.write(optStr)
44             else:
45                 print "do not support this type"
46                 print value
47             file.write("\n")
48     file.close()
49
50 if __name__=="__main__":
51     config = ConfigParser.ConfigParser()
52     config.readfp(codecs.open(cfgfile, "r", "utf-8"))
53     value = config.get("section","option")
54     #config.write(open("cfg2.ini", "w+"))
55     #config.write(codecs.open("cfg2.ini", "w+", "utf-8"))
56     print value
57
58     str='中文'
59     print str
60     print type(str)
61     print repr(str)
62
63     utf8str = str.decode('utf-8')
64     print utf8str
65     print type(utf8str)
66     print repr(utf8str)
67
68     ini_set("section","option",utf8str)

test.py

执行完程序后输出如下:

 1 1 >>>
 2 2 中文字符串
 3 3 涓枃
 4 4 <type 'str'>
 5 5 '\xe4\xb8\xad\xe6\x96\x87'
 6 6 中文
 7 7 <type 'unicode'>
 8 8 u'\u4e2d\u6587'
 9 9 >>>
10 output of test.py

Output of test.py

新的cfg.ini内容如下:

转载于:https://www.cnblogs.com/zhaoweiwei/p/ConfigParser.html

python2.7 内置ConfigParser支持Unicode读写相关推荐

  1. SpringBoot内置Tomcat支持多大并发量和连接数

    SpringBoot内置Tomcat,再默认设置中,Tomcat的最大线程数是200,最大连接数是10000.支持的并发量是指连接数,200个线程如何处理10000条连接的? Tomcat有两种处理连 ...

  2. LT8711UXE1,Type-C/DP1.2 转 HDMI2.0,内置HDCP,支持4k 60Hz向下兼容

    1. 描述 LT8711UXE1 是一款高性能 Type-C/DP1.2 至 HDMI2.0 转换器,设计用于将 USB Type-C 源或 DP1.2 源连接到 HDMI2.0 接收器.LT8711 ...

  3. junit5_JUnit 5和Selenium –使用Selenium内置的`PageFactory`实现页面对象模式

    junit5 Selenium是一组支持浏览器自动化的工具和库,主要用于Web应用程序测试. Selenium的组件之一是Selenium WebDriver,它提供客户端库,JSON有线协议(与浏览 ...

  4. idea内置junit5_JUnit 5和Selenium –使用Selenium内置的`PageFactory`实现页面对象模式

    idea内置junit5 Selenium是一组支持浏览器自动化的工具和库,主要用于Web应用程序测试. Selenium的组件之一是Selenium WebDriver,它提供客户端库,JSON有线 ...

  5. JUnit 5和Selenium –使用Selenium内置的`PageFactory`实现页面对象模式

    Selenium是一组支持浏览器自动化的工具和库,主要用于Web应用程序测试. Selenium的组件之一是Selenium WebDriver,它提供客户端库,JSON有线协议(与浏览器驱动程序进行 ...

  6. python中函数包括标准库函数吗_Python标准库:内置函数divmod(a, b)

    本函数是实现a除以b,然后返回商与余数的元组. 如果两个参数a,b都是整数,那么会采用整数除法,结果相当于(a//b, a % b).如果a或b是浮点数,相当于(math.floor(a/b), a% ...

  7. Spark团队开源新项目MLflow发布0.2版本,内置TensorFlow集成

    译者 | 无明 编辑 | Natalie AI 前线导读: 在今年的 Spark+AI 峰会上,Spark 团队推出了 MLflow,一个开源的用于简化机器学习生命周期的平台.从首次发布到现在的三周时 ...

  8. Unity3d shader内置矩阵

    内置矩阵 支持的矩阵(float4x4): UNITY_MATRIX_MVP        当前模型视图投影矩阵 UNITY_MATRIX_MV           当前模型视图矩阵 UNITY_MA ...

  9. iOS应用内置付费详尽攻略

    我最近正在制作的一个程序里面,我就决定先把程序免费(其中只包含一个故事),然后把更多的故事放在in-app purchase里面.在这篇教程里面,你将会学到如何使用程序内置付费来解琐本地程序里面的内容 ...

  10. angularjs读书笔记:angularjs内置过滤器总结——摘自《Angularjs权威教程》

    过滤器用来格式化需要展示给用户的数据.AngularJS有很多实用的内置过滤器,同时也提 供了方便的途径可以自己创建过滤器. 在HTML中的模板绑定符号{{ }}内通过|符号来调用过滤器.例如,假设我 ...

最新文章

  1. 再和“面向对象”谈恋爱 - 对象简介(一)
  2. Java 根据comboBox选择结果显示JTable
  3. 2440裸机编程之四 外部中断
  4. 数据挖掘-聚类分析(Python实现K-Means算法)
  5. AddOutParameter引发类型问题
  6. 入门干货之用DVG打造你的项目主页-Docfx、Vs、Github
  7. 囊括计算机 电子信息仿真技术,什么是虚拟现实?
  8. C++ Socket编程步骤
  9. glide加载gif图不显示动画_关于glide加载gif问题
  10. grid php 用法,grid布局主要用法
  11. Java中单例设计模式总结
  12. 用Hello World校验Docker的安装
  13. paip.基于HTML gui界面的javascript JS实现SLEEP。。
  14. redhat linux ssh服务,Redhat6开启ssh
  15. 使用百度云API进行人脸对比
  16. Navicat工具中数据库导入导出
  17. TensorFlow Probability 联合分布变分推断工具,估计权重的贝叶斯可信区间更简单
  18. 计算机英语构词法,计算机专业英语的构词方法论文
  19. linux 端口耗尽,短连接以致端口耗尽
  20. SPSS数据分析前,异常值处理

热门文章

  1. Splash 简介与安装
  2. Java 8 Stream
  3. 【LOJ】 #2025. 「JLOI / SHOI2016」方
  4. 使用nvDXT.exe把图片转换成dds图片【转】
  5. 前++和后++引发的血案
  6. 公安部4号令中关于电子邮服务器
  7. vue学习(9)-路由守卫
  8. Flex 布局学习笔记
  9. Node js模块系统
  10. 最大值、数据排序、九九乘法表、杨辉三角