数据持久化

数据持久化

1. 文件操作

计算机的文件,就是存储在某种 长期储存设备 上的一段 数据

长期存储设备包括:硬盘、U 盘、移动硬盘、光盘…

文本文件和二进制文件

  • 文本文件
    • 可以使用 文本编辑软件 查看
    • 本质上还是二进制文件
    • 例如:python 的源程序
  • 二进制文件
    • 保存的内容 不是给人直接阅读的,而是 提供给其他软件使用的
    • 例如:图片文件、音频文件、视频文件等等
    • 二进制文件不能使用 文本编辑软件 查看

1.1 文件的基本操作

操作文件的函数/方法

Python 中要操作文件需要记住 1 个函数和 3 个方法

序号函数/方法说明
01open打开文件,并且返回文件操作对象
02read将文件内容读取到内存
03write将指定内容写入文件
04close关闭文件
  • open 函数负责打开文件,并且返回文件对象
  • read/write/close 三个方法都需要通过 文件对象 来调用

1.1.1 读取文件

open

函数的第一个参数是要打开的文件名(文件名区分大小写)

  • 如果文件 存在,返回 文件操作对象

  • 如果文件 不存在,会 抛出异常

  • read 方法可以一次性 读入 并 返回 文件的 所有内容

  • close方法负责关闭文件

    • 如果 忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
  • 注意:read 方法执行后,会把 文件指针 移动到 文件的末尾

# 1. 打开 - 文件名需要注意大小写
file = open("README")

# 2. 读取
text = file.read()
print(text)

# 3. 关闭
file.close()

1.1.2 打开文件的方式

  • open 函数默认以 只读方式 打开文件,并且返回文件对象

语法如下:

f = open("文件名", "访问方式")
访问方式说明
r以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常
w以只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a以追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入
r+以读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常
w+以读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a+以读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入

提示

  • 频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写 的方式来操作文件

写入文件示例

# 打开文件
f = open("README", "w")

f.write("hello python!\n")
f.write("今天天气真好")

# 关闭文件
f.close()

1.1.3 按行读取文件内容

read 方法默认会把文件的 所有内容 一次性读取到内存

如果文件太大,对内存的占用会非常严重

readline 方法

readline 方法可以一次读取一行内容

方法执行后,会把 文件指针 移动到下一行,准备再次读取

读取大文件的正确姿势

1.2目录操作

  • 在 终端 / 文件浏览器、 中可以执行常规的 文件 / 目录 管理操作,例如:

    • 创建、重命名、删除、改变路径、查看目录内容、……
  • Python 中,如果希望通过程序实现上述功能,需要导入 os 模块

1.2.1 文件操作

序号方法名说明示例
01rename重命名文件os.rename(源文件名, 目标文件名)
02remove删除文件os.remove(文件名)

1.2.2 目录操作

序号方法名说明示例
01listdir目录列表os.listdir(目录名)
02mkdir创建目录os.mkdir(目录名)
03rmdir删除目录os.rmdir(目录名)
04getcwd获取当前目录os.getcwd()
05chdir修改工作目录os.chdir(目标目录)
06path.isdir判断是否是文件os.path.isdir(文件路径)

提示:文件或者目录操作都支持 相对路径 和 绝对路径

2. excel

openpyxl 是一个Python库,用于读取/写入Excel 2010 xlsx / xlsm / xltx / xltm文件。

它的诞生是因为缺少可从Python本地读取/写入Office Open XML格式的库。

Excel 文件三个对象

workbook: 工作簿,一个excel文件包含多个sheet。
sheet:工作表,一个workbook有多个,表名识别,如“sheet1”,“sheet2”等。
cell: 单元格,存储数据对象

1、openpyxl 读写单元格时,单元格的坐标位置起始值是(1,1),即下标最小值为1,否则报错!

2、openpyxl 支持直接横纵坐标访问,如 A1,B2…

2.1 创建工作簿

只需导入Workbook 对象就可以创建工作簿

# -*- coding: utf-8 -*-
from openpyxl import Workbook
# 创建工作簿
wb = Workbook()

如果想写入数据就需要获取一张表

表明创建时会自动命名。它们按顺序编号(Sheet,Sheet1,Sheet2等)。可以随时通过Worksheet.title属性更改此名称:

# 创建一张表
sheet = wb.active
sheet.title = '表1'

# 创建新表
sheet2 = wb.create_sheet('表2')

# 通过表名获取表
sheet1 = wb['表1']

2.2 写入操作

现在我们知道了如何获取工作表,可以开始修改单元格内容了。单元格可以直接作为工作表的键进行访问:

这将使单元格返回A4,如果尚未存在,则创建一个单元格。可以直接分配值:

# 写入值
sheet['A1'] = 42

还有 Worksheet.cell() 方法可以更方便操作。

sheet.cell(row=2, column=5).value = 99
sheet.cell(row=3, column=5, value=100)

逐行写

# 行内容可以直接被列表覆盖
# ws.append(iterable)
# 添加一行到当前sheet的最底部(即逐行追加从第一行开始)
# iterable必须是list,tuple,dict,range,generator类型的。
# 1,如果是list,将list从头到尾顺序添加。
# 2,如果是dict,按照相应的键添加相应的键值。
ws.append(['This is A1''This is B1''This is C1'])
ws.append({'A': 'This is A1''C': 'This is C1'})
ws.append({1: 'This is A1'3: 'This is C1'})

同时可以遍历单元格

2.3 案例:

将九九乘法表写入excel表

# 写入九九乘法表
ws9 = wb.create_sheet('九九乘法表')
i = 1
while i < 10:
    j = 1
    while j <= i:
        # print('{} * {} = {}'.format(j, i, j * i), end='\t')
        ws9.cell(row=i, column=j).value = '{} * {} = {}'.format(j, i, j * i)
        j += 1
    i += 1 

2.4 读表操作

# 打开文件:
from openpyxl import load_workbook
wb = load_workbook('sample.xlsx')
# 通过表名获取获取 sheet:
table = wb['九九乘法表']

# 获取行数和列数:
rows = table.max_row
cols = table.max_column
print(rows, cols)

# 获取单元格值:
# 获取表格内容,是从第一行第一列是从1开始的,注意不要丢掉 .value
Data = table.cell(row=1, column=1).value
print(Data)

# 获取所有表名
sheet_names = wb.sheetnames
print(sheet_names[0])
ws = wb[(wb.sheetnames[0])]  # index为0为第一张表
# 活动表表名
print(wb.active.title)

逐行读取

# 逐行读 ws9['A1:I9']: 例如('A1:C4')
# 返回一个生成器, 注意取值时要用value,例如:
for row in table['A1:I9']:
    for cell in row:
        print(cell.value)

显示有多少张表

print(wb.sheetnames)
# 显示表名,表行数,表列数
print(ws9.title)
print(ws9.max_row)
print(ws9.max_column)

保存文件

wb.save("sample1.xlsx")

2.5 操作实例

将猫眼爬虫的数据保存到 Excel 表。

3. json

目的: 将 Python 对象编码为 JSON 字符串,并将 JSON 字符串解码为 Python 对象。

json 模块提供了 API,将内存中的 Python 对象转换为 JSON 序列。JSON 具有以多种语言(尤其是 JavaScript)实现的优点。它在 REST API 中 Web 服务端和客户端之间的通信被广泛应用,同时对于应用程序间通信需求也很有用。 下面演示如何将一个Python数据结构转换为JSON:

3.1 编码和解码

Python 的默认原生类型(strintfloatlisttuple,和dict)。

import json

data = {
    'name': 'ACME',
    'shares': 100,
    'price': 542.23
}

json_str = json.dumps(data)
print(json_str)

表面上看,类似于 Python repr() 的输出。虽然内容看似是一样,但是类型却已经发生改变

print(type(json_str))

从无序的字典到有序的字符串,这个过程被称之为序列化。

最终我们将json保存到文件

with open('data.json', mode='w', encoding='utf-8') as f:
    f.write(json_str)

3.1.1 中文字符问题

import json

data = {
    'name': '青灯',
    'shares': 100,
    'price': 542.23
}

# 将字典序列化为json
json_str = json.dumps(data)

# 写入 json 数据
with open('data.json', mode='w', encoding='utf-8') as f:
    f.write(json_str)
# filename:data.json
{"name": "\u9752\u706f", "shares": 100, "price": 542.23}

解决办法: json_str = json.dumps(data, ensure_ascii=False)

3.2 读取数据

将json数据变为字典类型的这个过程被称之为反序列化

# 读取 json 数据
with open('data.json', 'r', encoding='utf-8') as f:
    # 反序列化
    data = json.load(f)

# 打印数据
print(data)
print(data['name'])

3.3 格式化输出

JSON 的结果是更易于阅读的。dumps() 函数接受几个参数以使输出更易读结果。

import json

data = {'a': 'A''b': (24)'c': 3.0}
print('DATA:'repr(data))	# DATA: {'a': 'A', 'b': (2, 4), 'c': 3.0}

unsorted = json.dumps(data)
print('JSON:', json.dumps(data))	# JSON: {"a": "A", "b": [2, 4], "c": 3.0}

编码,然后重新解码可能不会给出完全相同类型的对象。

特别是,元组成为了列表。

JSON跟Python中的字典其实是一样一样的,事实上JSON的数据类型和Python的数据类型是很容易找到对应关系的,如下面两张表所示。

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
True / Falsetrue / false
Nonenull

4. CSV模块简介

csv文件格式是一种通用的电子表格和数据库导入导出格式。最近我调用RPC处理服务器数据时,经常需要将数据做个存档便使用了这一方便的格式。

python中有一个读写csv文件的包,直接import csv即可。利用这个python包可以很方便对csv文件进行操作,一些简单的用法如下。

4.1 写入文件

我们把需要写入的数据放到列表中,写文件时会把列表中的元素写入到csv文件中。

import csv

ll = [[1, 2, 3, 4],
      [1, 2, 3, 4],
      [5, 6, 7, 8],
      [5, 6, 7, 8]]

with open('example1.csv', 'w', newline='') as csvfile:
    """
    delimiter: 分割符
    """
    spamwriter = csv.writer(csvfile, delimiter=',')
    for l in ll:
        spamwriter.writerow([1, 2, 3, 4])

可能遇到的问题:直接使用这种写法会导致文件每一行后面会多一个空行。使用 newline='' 解决

使用 open 直接写入

 with open('example2.csv', 'w') as csvfile:
    """
    delimiter: 分割符
    """
    for l in ll:
        csvfile.write(",".join(map(str, l)))
        csvfile.write('\n')

4.2 读取文件

import csv

with open('example.csv', encoding='utf-8') as f:
    csv_reader = csv.reader(f)
    for row in csv_reader:
        print(row)

file:example.csv csv 数据

['1', '2', '3', '4']
['1', '2', '3', '4']
['1', '2', '3', '4']
['1', '2', '3', '4']

默认的情况下, 读和写使用逗号做分隔符(delimiter),当遇到特殊情况是,可以根据需要手动指定字符, 例如:

with open('example.csv', encoding='utf-8') as f:
    reader = csv.reader(f, delimiter=',')
    for row in reader:
        print(row)

上述示例指定冒号作为分隔符

有点需要注意的是,当用writer写数据时, None 会被写成空字符串,浮点类型会被调用 repr() 方法转化成字符串。所以非字符串类型的数据会被 str() 成字符串存储。所以当涉及到 unicode 字符串时,可以自己手动编码后存储或者使用csv提供的 UnicodeWriter

4.3 写入与读取字典

csv 还提供了一种类似于字典方式的读写,方式如下:

class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel'*args, **kwds)

class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel'*args, **kwds)

其中 fieldnames 指定字典的 key 值,如果 reader 里没有指定那么默认第一行的元素,在 writer 里一定要指定这个。

# %% 写

import csv

with open('names.csv', 'w') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
    writer.writerow({'first_name': 'Lovely'})
    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

# %% 读
import csv

with open('names.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        print(row['first_name'], row['last_name'])

5. mysql数据库

MySQL 是一个 DBMS(数据库管理系统),由瑞典 MySQLAB 公司开发,目前属于 Oracle (甲骨文)公司,MySQL 是最流行的关系型数据库管理系统(关系数据库,是建立在关系数据库模型基础上的数据库,借助于集合代数等概念和方法来处理数据库中的数据)。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发者都选择 MySQL 作为网站数据库。MySQL 使用 SQL 语言进行操作。

概念对比

  • DB:数据库,存放数据的容器
  • DBMS:数据库管理系统,用于管理DB
  • SQL:结构化查询语言,是关系型数据库的通用语言

RDBMS 术语

在我们开始学习MySQL 数据库前,让我们先了解下RDBMS的一些术语:

  • 数据库: 数据库是一些关联表的集合。
  • 数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
  • 列: 一列(数据元素) 包含了相同类型的数据, 例如邮政编码的数据。
  • **行:**一行(=元组,或记录)是一组相关的数据,例如一条用户订阅的数据。

5.1 创建

5.1.1 创建数据库

创建一个数据库,给它一个名字,比如 python,以后的几次操作也是对 python 这个数据库进行操作。 语句格式为 CREATE DATABASE <数据库名字>;,(注意不要漏掉分号 ;),前面的 CREATE DATABASE 也可以使用小写,具体命令为:

-- create database 数据库名 charset=utf8;
-- 例:
create database python charset=utf8;

接下来的操作,就在刚才创建的 python 中进行,由于一个系统中可能会有多个数据库,要确定当前是对哪一个数据库操作,使用语句 use <数据库名字>

mysql> use python;

5.1.2 创建数据表

数据表(table)简称表,它是数据库最重要的组成部分之一。数据库只是一个框架,表才是实质内容。

而一个数据库中一般会有多张表,这些各自独立的表通过建立关系被联接起来,才成为可以交叉查阅、一目了然的数据库。

如下便是一张表:

IDnamephone
01Tom110110110
02Jack119119119
03Rose114114114

在数据库中新建一张表的语句格式为:

CREATE TABLE 表的名字(列名a 数据类型(数据长度),列名b 数据类型(数据长度));

我们尝试在 python 中新建一张表 employee,包含姓名,ID 和电话信息,所以语句为:

mysql> CREATE TABLE employee (id int(10),name char(20),phone int(12));
Query OK, 0 rows affected (0.00 sec)

5.2 pymysql 操作数据库

5.2.1 安装

pymysql是python的一个第三方库,使用 pip install pymsyql 可以直接安装

5.2.2 链接数据库

链接数据库对象:调用 pymysql.connect() 方法

conn=pymysql.connect(参数列表)

参数:

  • host - 数据库服务器所在的主机
  • user - 登录的用户名
  • password - 要使用的密码。
  • database - 要使用的数据库,None不使用特定的数据库。
  • port - 要使用的MySQL端口,默认通常都可以。(默认值:3306)
  • charset - 你要使用的Charset。
  • db - 数据库的别名。(与MySQLdb兼容)
  • passwd - 密码的别名。(与MySQLdb兼容)

5.2.3 执行 sql 命令

执行 sql 命令,需要调用 Connection 对象的 cursor() 方法创建一个游标(Cursor)对象。

获取Cursor对象:

cursor = conn.cursor()

使用 excute 执行查询指令

sql = '需要执行的命令'
cursor.excute(sql)

5.2.4 关闭链接

操作完了之后,需要关闭游标与链接

cursor.close()
conn.close()

5.3 插入数据

使用游标向数据库插入数据

# 插入一条数据
one_data = "insert into goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default); "

cursor.execute(one_data)

回滚

try:
    # 执行SQL语句
    cursor.execute("insert into goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default); ")
    # 提交事务
    conn.commit()
except Exception as e:
    # 有异常,回滚事务
    conn.rollback()
cursor.close()
conn.close()

5.4 查询数据

# 查询数据
cursor.execute("SELECT * FROM goods")
# 读取一条数据
rest = cursor.fetchone()
print(rest)
# 读取所有数据
rest = cursor.fetchall()
print(rest)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值