文件和异常
实际开发中需要对数据进行持久化操作,而数据的持久化最简单直接的方式就是将数据保存到文件中。python中实现文件的读写操作非常简单,通过内置的open函数,可以指定文件名、操作模式、编码信息等。
| 操作方式 | 具体含义 | 
|---|---|
| ‘r’ | 读取 | 
| ‘w’ | 写入覆盖 | 
| ‘x’ | 写入,文件已经存在则产生异常 | 
| ‘a’ | 追加,不覆盖 | 
| ‘b’ | 二进制模式 | 
| ‘t’ | 文本模式 | 
| ‘+’ | 更新可读可写 | 
|  | |
| ## 读写文本文件 | |
| 读取文本文件时,需要在使用open函数时指定好带路径的文件名(可以使用相对路径或绝对路径)并将文件模式设置为’r’(如果不指定,默认值也是’r’),然后通过encoding参数指定编码(如果不指定,默认值是None,那么在读取文件时使用的是操作系统默认的编码) | 
def main():
    f = open("思考", 'r', encoding="utf-8")
    print(f.read)
    f.close()
if __name__ == "__main__":
    main如果文件不存在将会产生异常,所以要有try-except操作,或者或许的with操作
def main():
    f = None
    try:
        f = open("思考", 'r', encoding='utf-8')
        print(f.read())
    except FileNotFoundError:
        print("无法打开指定的文件")
    except LookupError:
        print("指定了未知的编码")
    except UnicodeDecodeError:
        print("读取文件时解码错误")
    finaaly:
        if f:
            f.close()
if __name__ == "__main__":
    main()with上下文环境
def main():
    try:
        with open("思考",'r',encoding='utf-8') as f:
            print(f.read())
    except FileNotFoundError:
        print("无法打开指定的文件")
    except LookupError:
        print("指定了未知的编码")
    except UnicodeDecodeError:
        print("读取文件时解码错误")
if __name__ == "__main__":
    main()还可以for-in循环逐行的读取或者用readlines方法将文件按行读取
import time
def main():
    # 一次性读取整个文件内容
    with open("thinking", 'r', encoding='utf-8') as f:
        print(f.read())
    # 通过for-in循环逐行读取
    with open("thinking", 'r', encoding='utf-8') as f:
        for line in f:
            print(line, end='')
            time.sleep(0.5)
    print()
    # 读取文件按行读取到列表中
    with open("thinking", 'r', encoding='utf-8') as f:
        lines = f.readlines()
    print(lines)
if __name__ == "__main__":
    main()写入文件
from math import sqrt
def is_prime(n):
    '''判断是不是素数'''
    assert n > 0
    for factor in range(2, int(sqrt(n)) + 1):
        if n % factor == 0:
            retrun False
    return True if n != 1 else False
def main():
    filenames = ('a.txt', 'b.txt'. 'c.txt')
    fs_list = []
    try:
        for filename in filenames:
            fs_list.append(open(filename, 'w', encoding='utf-8'))
        for number in range(1, 10000):
            if is_prime(number):
                if number < 100:
                    fs_list[0].write(str(number) + '\n')
                elif number < 1000:
                    fs_list[1].write(str(number) + '\n')
                else:
                    fs_list[2].write(str(number) + '\n')
    except IOError as ex:
        print(ex)
        print("写文件发生错误")
    finally:
        for fs in fs_list:
            fs.close()
    print("操作完成")
if __name__ "__main__":
    main()读写二进制文件 复制图片
def main():
    try:
        with open("guido.jpg", "rb") as fs1:
            data = fs1.read()
            print(type(data))  # bytes
        with open("吉多.jpg", "wb") as fs2:
            fs2.write(data)
    except FileNotFoundError as e:
        print("指定的文件无法打开")
    except IOError as e:
        print("读写文件时出现错误")
    print("程序执行结束")
if __name__ == "__main__":
    main()读写JSON文件
如果希望把一个列表或者一个字典中的数据保存到文件中,就以json格式进行保存
json  “JavaScript Object Notation”,它本来是JavaScript语言中创建对
象的一种字面量语法,现在已经被广泛的应用于跨平台跨语言的数据交换,因为json也是纯文本,任何系统任何语言处理纯文本都是没有问题的,目前json基本上已经取代了XML作为异构系统间交换数据的事实标准。
JSON示例
{
    "name": "bayhax",
    "age": "24",
    "qq": 14023233,
    "friends": ["尹天仇", "阿星"],
    "cars": [
        {"brands": "BYD", "max_speed": 180},
        {"brands": "Audi", "max_speed": 280},
        {"brands": "Benz", "max_speed": 320}
    ]
}JSON格式跟Python中的字典是一样的
| JSON | Python | 
|---|---|
| object | dict | 
| array | list | 
| string | str | 
| number(int/real) | int/float | 
| true/false | True/False | 
| null | None | 
| Python | JSON | 
|---|---|
| dict | object | 
| list,tuple | array | 
| str | string | 
| int float int- & float-derived Enums | number | 
| True/False | true/false | 
| None | null | 
使用Python中的json模块就可以将字典或列表以JSON格式保存到文件中
import json
def main():
    mydict = {
        "name": "bayhax",
        "age": "24",
        "qq": 14023233,
        "friends": ["尹天仇", "阿星"],
        "cars": [
            {"brands": "BYD", "max_speed": 180},
            {"brands": "Audi", "max_speed": 280},
            {"brands": "Benz", "max_speed": 320}
        ]
    }
    try:
        with open("data.json", "w",encoding="utf-8") as f:
            json.dump(mydict, f)
    except IOError as e:
        print(e)
    print("保存数据完成")
if __name__ "__main__":
    main()json模块四个重要的函数
- dump 将Python对象按照JSON格式序列化到文件中
- dumps 将Python对象处理成JSON格式的字符串
- load 将文件中的JSON数据反序列化成对象
- loads 将字符串的内容反序列化成Python对象
序列化和反序列化
“序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换为可以存储或传输的形式,这样在需要的时候能够恢复到原先的状态,而且通过序列化的数据重新获取字节时,可以利用这些字节来产生原始对象的副本(拷贝)。与这个过程相反的动作,即从一系列字节中提取数据结构的操作,就是反序列化(deserialization)”。
目前绝大多数网络数据服务(或称之为网络API)都是基于HTTP协议提供JSON格式的数据,关于HTTP协议的相关知识,可以看看阮一峰老师的《HTTP协议入门》,如果想了解国内的网络数据服务,可以看看聚合数据和阿凡达数据等网站,国外的可以看看{API}Search网站。下面的例子演示了如何使用requests模块(封装得足够好的第三方网络访问模块)访问网络API获取国内新闻,如何通过json模块解析JSON数据并显示新闻标题,这个例子使用了天行数据提供的国内新闻数据接口,其中的APIKey需要自己到该网站申请。
import requests
import json
def main():
    resp = requests.get('http://api.tianapi.com/guonei/?key=APIKey&num=10')
    data_model = json.loads(resp.text)
    for news in data_model['newslist']:
        print(news['title'])
if __name__ == '__main__':
    main()在Python中要实现序列化和反序列化除了使用json模块之外,还可以使用pickle和shelve模块,但是这两个模块是使用特有的序列化协议来序列化数据,因此序列化后的数据只能被Python识别