介绍
一直不太喜欢使用命令行,所以去年年底的技术创新中,使用TkInter来开发小工具。结果花费了大量的时间来学习TkInter ui的使用。
最近想整理该工具,使用命令行的形式,然后将该工具做成exe的形式进行分发。在工作一开始就遇到了编码的问题。
在脚本中有如下代码,用来接收用户交互式输入的ip。
server = raw_input("请输GIS Server IP:")
在脚本文件的第一行,我已经加了如下代码
# -*-coding: utf-8 -*-
但是在windows 的控制台执行的时候,出现了乱码。有点不解,因为自己一直以来在python中,处理中文都是在文件头加入该代码。
通过搜索发现,是因为在windows cmd 默认的使用的cp936的编码。既然知道使用这种编码则将编码改为如下:
# -*-coding: cp936-*-
但是得到如下的错误:
SyntaxError: encoding problem: cp936 with BOM
百思不得其解。作为懒癌患者,就想绕过去。则采用如下方式,对单独字符串进行编码。
userName=raw_input("请输入站点管理员用户名:".decode("utf-8").encode("cp936"))
这样重要在cmd中可以正常的输出中文了。但是问题来了,我的脚本中,有上百行代码有中文。每个地方都这么写,感觉偷懒不成,反被*。
这个时候,通过搜索。逐步的发现了问题的原因。这是因为python有几个层次的编码。分别是:
- 字符串变量级别编码
- 脚本级别的编码
- py文件级别的编码
- 显示窗口的编码
字符串变量的编码
对单个字符串转码,可以使用:**encode()**编码成可以显示的。通常对字符串不能由一个编码直接转换为另一个编码。通常需要解码到Unicode,然后对unicode字符串重新的编码。比如上面的示例。
脚本的编码
上面通过设置 #coding:utf-8设置的就是脚本里面内容的编码。也就是该脚本文件中所有的字符串变量都采用该处设置的编码方式。
##py文件的编码
py文件的编码,默认的是ANSI。但是也可以使用utf-8,unicode编码。
显示窗口的编码
上面的几种情况,中文在运行阶段不会出错。但是这些中文还不一定能够正常的显示。能否正常的显示,还有显示窗口支持的编码决定。比如cmd中中文支持GBK和cp936,所以代码中的字符串需要编码到这两种才可以显示。
##测试
- 当py文件的编码为utf-8的时候。代码中唔需要添加#coding:utf-8 。脚本中的中文,在运行过程不会报错。
- 当py文件的编码为ANSI的时候。如代码中没有显示的添加 ** --coding:utf-8 -- **,则当代码中出现中文的时候,运行脚本的时候。会出现如下错误
SyntaxError: Non-ASCII character '\xe4' in file
- 当py文件设置为utf-8,而显示设置代码编码为#coding:936。则会出现ncoding problem: cp936 with BOM的错。这个时候,将py文件的编码改为ANSI即可。
##结论
通过上面的测试,有几个结论:
- 编码有层次结构。文件编码影响脚本内容编码,脚本内容编码决定 其中的字符串编码。
- 当字符串显示设置了编码的时候。字符串的编码为显示设置的编码,此时文件和脚本编码不起作用。当字符串没有显示设置编码的时候,则采用上一级编码决定。
- 所以设置这三种编码的时候,需要确保三种编码之间能够转换。否则会出现上面列举的错误。