0%

python011.md

文件和异常

实际开发中需要对数据进行持久化操作,而数据的持久化最简单直接的方式就是将数据保存到文件中。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识别