熟悉文件操作
2017年1月14日15:43:48
开始进入文件读取操作。第一步,先阅读AIMinder/Py103/wiki/IdxPy103Reference当中指定的“文件读写参考”资料,从该参考资料的URL可知这篇文档是Python3的参考文档,其中的内容提到:
文件读取可分为"text mode"和“binary mode”,前者适用于文本文件,后者适用于非文本文件。
"text mode"与“binary mode”在操作时候有些差异性,比如适用seek()函数时后者更灵活。当文件以“text mode”读写时,它会以特定的编码格式去操作文件内容,如果不提前指定格式那么就依赖于系统平台的默认编码格式了(这个问题便是前几天学习《LPTHW》时候遇到的在源代码文件前面加上
-*- coding: utf-8 -*-的疑问。)。提倡在操作文件的时候使用with语句。
使用json来存储结构化的数据。
阅读完这篇参考之后无法直接在脑海里构建出读取天气文件的代码,因此决定回去参考《LPTHW - Exercise 15: Reading Files》当中的例子来编写最初的代码。
用户需求与第一个版本
2017年1月14日16:20:18
《Exercise 15: Reading Files》当中的例子使用了命令行参数,也即是在执行python脚本的时候给定要操作的文件名称,当前的任务是不需要的,因为最后的成品是根据用户输入的城市来获取该城市的天气,很显然天气数据文件是属于软件内部的数据仓库存在,对用户不可见。因此,我们也不需要使用命令行参数,代码如下:
weather_info = open(weather_info.txt)
print weather_info.read()
不幸的是执行不通过,提示:
> python Coderound1_ReadWeatherFile.py
Traceback (most recent call last):
File "Coderound1_ReadWeatherFile.py", line 2, in <module>
weather_info = open(weather_info.txt)
NameError: name 'weather_info' is not defined
我是参考示例中的代码才写出上面两行的,想了想之后发现调用open函数的时候hardcode的文件名是 weather_info.txt,理应是'weather_info.txt',也就是需要加上单引号。修正之后执行,出现如下问题:
...
闆峰窞,鏅撮棿澶氫簯
寰愰椈,鏅撮棿澶氫簯
寤夋睙,鏅?
璧ゅ潕,鏅撮棿澶氫簯
閬傛邯,鏅?
鍧″ご,鏅撮棿澶氫簯
闇炲北,鏅撮棿澶氫簯
楹荤珷,鏅撮棿澶氫簯
姹熼棬,鏅撮棿澶氫簯
寮€骞?澶氫簯
...
这东东是什么,看不清楚?好在因为刚在前面提到字符编码的问题,并且shippomiru在提交作业之后与闪闪的讨论,基本可以确定与字符编码有关系,因此在源代码文件的开头添加*- coding: utf-8 -*-之后再运行。
乱码问题
2017年1月14日17:16:01
本来以为在文件头上添加了utf-8编码声明之后问题就解决了,实际上的尝试并没有如此简单。
- utf-8编码声明
为了解决乱码,先缩小了问题范围:写了如下仅仅打印“你好”的测试代码:
# -*- coding: utf-8 -*-
import sys
encoding_type = sys.getfilesystemencoding()
hello = "你好"
print hello.decode('utf-8').encode(encoding_type)
上面这段代码在Windows下面是可以工作的,里面涉及到了两种编码方式:
源文件编码:也就是在源代码文件开头声明的
# -*- coding: utf-8 -*-,它决定了文件当中的内容在存储介质上所使用的编码方式,代码中的中文也就以utf-8的格式进行编码。系统编码:调用Python的print接口输出“你好”的时候使用的编码格式便是系统编码,所以如果此时不使用decode/encode函数来进行编解码转换,输出也将是乱码。
如下的代码没有进行编解码转换,会显示乱码。
# -*- coding: utf-8 -*-
import sys
encoding_type = sys.getfilesystemencoding()
hello = "你好"
print hello
输出:
lianbche@5CG44636XG D:\Learning\git\Py103\Chap1\project
> python Coderound1_EncodingChinese.py
浣犲ソ
综上,在源代码最开头所声明的编码方式是指该文件被解析、存储时所采用的编码方式。
- 另一个问题
粗浅地理解了上面的内容,其实还无法解决读取文件显示乱码的问题。因为测试代码里面的中文“你好”直接存在于源代码文件中,所以我可以通过声明编码方式来决定如何编码它并如何进行对应的转换。而目前的主要问题是我从其他仓库下载过来的weather_info.txt文件的编码方式是什么我并不知道,但我还是改写了代码来尝试:
# -*- coding: utf-8 -*-
import sys
encoding_type = sys.getfilesystemencoding()
weather_info = open('weather_info.txt')
content = weather_info.read()
print content.decode('utf-8').encode(encoding_type)
weather_info.close()
输出为:
...
塔城,晴间多云
裕民,晴间多云
额敏,晴间多云
和布克赛尔,晴
托里,晴
乌苏,晴
沙湾,阴
哈密,晴
巴里坤,晴间多云
...
成功了。根据结果反向推测可以知道该文件在生成时候的编码方式便是utf-8,所以去使用utf-8编码它然后再转换进行输出显示才会正常。突然间在一下子领悟到为什么在源代码当头要统一声明编码方式的重要性了:可以让文件更具有移植性。试想,如果教练团生成这个文件时使用了另外一套编码格式,那我不知道要尝试到猴年马月才能正常解码它。
同时,我在测试当中将上面代码第一行的# -*- coding: utf-8 -*-删除之后发现依然可以正常输出(要知道在前一个例子当中是不可以的),更加相信了“weather_info.txt是以utf-8编码”的推测。