数据持久化
数据持久化通常指将数据保存到磁盘或其他永久存储介质中以便以后使用。
以下是一些在Python中进行数据持久化的常用方法:
- 文件操作:可以使用Python内置的文件操作来将数据保存到文本文件中,例如使用open()函数打开文件并使用read()、write()、readlines()等方法来读写文件。
- pickle模块:Python的pickle模块可以序列化Python对象并将其保存到文件中。反序列化后可以恢复原始对象。但是,pickle模块可能存在安全问题,因为它可以执行任意代码。
- shelve模块:Python的shelve模块使用key-value存储方式将Python对象保存到文件中。shelve是一种简单易用的持久化方案,它使用pickle来实现序列化和反序列化。
- 数据库:使用关系型数据库如MySQL、PostgreSQL、SQLite等或非关系型数据库如MongoDB、Redis等可以更好的管理和组织数据。Python提供了多个用于数据库操作的库,如SQLite3、MySQLdb、psycopg2、pymongo等。
选择哪种数据持久化方法取决于需要持久化的数据类型和应用场景。
下面我将数据持久化方式分为基于单文件的持久化与基于数据库(搜索引擎)的持久化来介绍,并举出实例,最后给出两种方式的可用代码包。
基于文件的数据持久化
Txt持久化 -------将数据存为txt文件
使用场景:
使用纯文本文件(.txt)进行持久化可以用于保存简单的文本数据,如配置信息、日志记录、报告等。例如,可以将程序运行时生成的日志信息写入文本文件,以便后续查看和分析。也可以将程序中的配置信息保存到文本文件中,方便程序下次启动时读取使用。此外,还可以将程序运行结果保存到文本文件中,以便后续分析和处理。总之,使用纯文本文件进行持久化是一种简单且通用的方式,可以满足很多基本的数据持久化需求。
# 打开文件进行写操作
with open('test.txt', 'w') as f:
f.write('Hello, world!')
# 打开文件进行读操作
with open('test.txt', 'r') as f:
contents = f.read()
print(contents)
什么是序列化?
序列化是将数据结构或对象转换为一系列位(通常是字节)以便存储或传输的过程。如在前后端交互时使用json传输数据。json就是一种序列化方式。
json持久化
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由于它易于阅读和编写,并且可以轻松地解析和生成,因此被广泛用于数据交换。
在Python中,JSON常用于将数据从一个应用程序传递到另一个应用程序。使用Python的json模块,可以将Python对象序列化为JSON格式,也可以将JSON格式的字符串反序列化为Python对象。常见的应用场景包括:
- API接口的数据传输:许多API接口都使用JSON格式作为数据传输的标准格式。
- Web开发中的前后端数据传输:在Web开发中,通常会将前端的数据用JSON格式传给后端,后端再将处理结果用JSON格式返回给前端。
- 数据存储:将数据以JSON格式写入文件中,或者将JSON格式的数据存储在数据库中。
下面是一个使用Python将Python对象序列化为JSON格式,并将JSON格式的字符串反序列化为Python对象的示例:
import json
# 将Python对象序列化为JSON格式
data = {
'name': 'John',
'age': 30,
'isMale': True,
'hobbies': ['reading', 'music', 'traveling']
}
json_str = json.dumps(data)
print(json_str)
# 将JSON格式的字符串反序列化为Python对象
data_from_json = json.loads(json_str)
print(data_from_json)
其中,json.dumps()方法将Python对象序列化为JSON格式的字符串,json.loads()方法将JSON格式的字符串反序列化为Python对象。
csv持久化 ------将数据到csv文件中
CSV(Comma Separated Values)是一种常见的纯文本文件格式,用于将数据以表格形式存储并传输。每行表示一行数据记录,每个字段之间使用逗号进行分隔。
以下是CSV文件的一些使用场景:
- 数据交换:CSV文件可以被不同的应用程序之间方便地交换数据,例如在不同的操作系统或不同的数据库之间。
- 数据备份:CSV文件也可以用作数据库备份格式,允许在不同的系统之间轻松备份和还原数据。
- 数据分析:CSV文件通常被用作数据分析和统计学的输入格式,因为它们可以轻松地从多种来源导入到分析工具中。
- 数据可视化:CSV文件也可以用于可视化数据,例如制作图表、地图和其他可视化效果。
在Python中,可以使用内置的csv模块来读写CSV文件。以下是一个简单的示例:
import csv
# 写入CSV文件
with open('data.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['Name', 'Age', 'Gender'])
writer.writerow(['Alice', '25', 'Female'])
writer.writerow(['Bob', '30', 'Male'])
# 读取CSV文件
with open('data.csv', 'r') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
print(row)
这个示例首先使用csv.writer将数据写入CSV文件,然后使用csv.reader读取CSV文件。
注意,csv.writer需要指定参数newline=''来避免在Windows系统中出现空行。
excel持久化
Excel是微软公司的一款电子表格软件,通常用于处理、分析和存储数据。Excel文件可以包含多个工作表,每个工作表都由行和列组成,可以将数据存储在单元格中,支持各种公式、图表和数据分析功能。
Excel文件的使用场景非常广泛,例如:
- 数据分析和统计:可以使用Excel对数据进行可视化分析和统计。
- 财务管理:可以使用Excel进行预算、财务分析和报告编制。
- 项目管理:可以使用Excel制定项目计划、进度跟踪和任务分配。
- 数据录入和处理:可以使用Excel对大量数据进行录入、清理和处理。
写入excel的方式如下:
# coding=utf-8
import openpyxl
# 创建一个工作簿对象
workbook = openpyxl.Workbook()
# 创建一个工作表对象
worksheet = workbook.active
# 设置表名
worksheet.title = "Sheet"
# 写入表头
worksheet.cell(row=1, column=1, value="姓名")
worksheet.cell(row=1, column=2, value="年龄")
worksheet.cell(row=1, column=3, value="性别")
# 写入数据
worksheet.cell(row=2, column=1, value="张三")
worksheet.cell(row=2, column=2, value=20)
worksheet.cell(row=2, column=3, value="男")
worksheet.cell(row=3, column=1, value="李四")
worksheet.cell(row=3, column=2, value=25)
worksheet.cell(row=3, column=3, value="女")
# 保存文件
workbook.save(filename="example.xlsx")
读取excel的方式如下:
# coding=utf-8
import pandas as pd
# 读取Excel文件
data = pd.read_excel('example.xlsx', sheet_name='Sheet')
# 打印读取的数据
print(data.head())
pkl持久化
pickle模块介绍
Pickle模块是Python中用于序列化和反序列化数据的标准模块之一。Pickle模块可以将Python对象序列化为字节流,也可以将字节流反序列化为Python对象。因此,使用Pickle模块可以轻松地将Python对象保存到文件中,也可以将Python对象通过网络发送到其他计算机。
pickle模块使用
import pickle
# 序列化
data = {'name': 'Jack', 'age': 18}
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
# 反序列化
with open('data.pkl', 'rb') as f:
data = pickle.load(f)
print(data)
在上面的示例中,我们首先定义了一个字典类型的数据data,然后使用Pickle模块将其序列化到文件data.pkl中。接着,我们使用Pickle模块将data.pkl文件反序列化为Python对象,并将其赋值给变量data。最后,我们输出变量data的值,即{‘name’: ‘Jack’, ‘age’: 18}。
pickle序列化数据有其优缺点:如果数据只需要在Python解释器中使用,并且安全性要求不高,那么可以考虑使用pickle序列化数据。但是如果需要跨平台使用,或需要更高的安全性,就需要考虑其他序列化方式。
基于数据库、搜索引擎的持久化
Mongo ----python如何将数据持久化到mongo?
pymongo模块使用
import pymongo
client = pymongo.MongoClient('mongodb://localhost:27017/')
db = client['mydb'] # 创建一个名为mydb的数据库
collection = db['mycollection'] # 创建一个名为mycollection的集合
data = {'name': '张三', 'age': 18, 'address': '北京市'}
result = collection.insert_one(data) # 将data插入到mycollection集合中
print(result.inserted_id) # 输出插入的数据的ID
以上代码连接到了名为mydb的数据库,然后创建了一个名为mycollection的集合。然后我们定义了一个字典类型的数据data,并将其插入到了mycollection集合中。最后,我们打印了插入数据的ID。
pymongo模块的缺点
- 比较底层:PyMongo虽然提供了丰富的API,但是与其他高层次的ORM框架相比,还是比较底层的。对于一些简单的操作,需要写较多的代码。
- 需要学习MongoDB:PyMongo是与MongoDB数据库进行交互的库,因此需要对MongoDB的基本概念和操作有一定的了解。
- 对于大型数据集的支持不足:对于大型数据集的查询和操作,PyMongo可能会存在性能瓶颈。这时候,需要使用MongoDB自身的分布式查询和分片功能来解决问题。
motor模块使用
# coding=utf-8
import asyncio
from motor.motor_asyncio import AsyncIOMotorClient
from bson.objectid import ObjectId
import time
# 定义MongoDB连接池
MONGO_CONNECTION_STRING = "mongodb://192.168.10.230:27010"
MONGO_MAX_CONNECTIONS = 100
class MongoClientPool:
def __init__(self):
self.pool = []
async def acquire(self):
if len(self.pool) == 0:
client = AsyncIOMotorClient(MONGO_CONNECTION_STRING, maxPoolSize=MONGO_MAX_CONNECTIONS)
return client
else:
return self.pool.pop()
async def release(self, client):
self.pool.append(client)
# 建立连接池
mongo_pool = MongoClientPool()
async def demo():
client = await mongo_pool.acquire()
db = client["test"]
collection = db["mycollection"]
# 插入文档
doc = {"name": "Alice", "age": 30}
result = await collection.insert_one(doc)
print("插入文档成功,文档ID为:", result.inserted_id)
# 查询文档
query = {"name": "Alice"}
result = await collection.find_one(query)
print("查询文档成功,结果为:", result)
# 更新文档
filter = {"name": "Alice"}
update = {"$set": {"age": 31}}
result = await collection.update_one(filter, update)
print("更新文档成功,影响的行数为:", result.modified_count)
# 删除文档
filter = {"name": "Alice"}
result = await collection.delete_one(filter)
print("删除文档成功,影响的行数为:", result.deleted_count)
await mongo_pool.release(client)
######################################################################################################################
# # 运行示例程序
async def main():
tasks = []
for i in range(10):
tasks.append(asyncio.create_task(demo()))
await asyncio.gather(*tasks)
start = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
end = time.time()
print("耗时:", end - start)
# 异步时间 ===> 耗时: 0.10602402687072754
#同步时间 ===> 0.8021814823150635
mysql
pymyql
使用Pymysql连接MySQL数据库需要先创建一个Connection对象,然后通过该对象创建一个Cursor对象,最后通过Cursor对象进行数据库操作。
import pymysql
# 创建Connection对象
conn = pymysql.connect(
host='localhost',
user='root',
password='',
database='test',
charset='utf8'
)
# 创建Cursor对象
cursor = conn.cursor()
# 执行SQL语句
sql = "SELECT * FROM user"
cursor.execute(sql)
# 获取查询结果
result = cursor.fetchall()
# 输出结果
for row in result:
print(row)
# 关闭连接
cursor.close()
conn.close()
aiomysql
# coding=utf-8
import asyncio
import aiomysql
mysql_host = '192.168.10.231'
# mysql_user = 'root'
mysql_user = 'mysql'
mysql_passwd = "123456"
mysql_db = 'google_smap'
mysql_port = 3306
sql = 'SELECT city.name_cn,city.country_code,city.id from city LIMIT 10;'
class MysqlAsyncPool:
def __init__(self, pool_size=5):
self.pool_size = pool_size
async def create_pool(self):
self.pool = await aiomysql.create_pool(
host=mysql_host,
port=mysql_port,
user=mysql_user,
password=mysql_passwd,
db=mysql_db,
charset='utf8',
autocommit=True,
maxsize=self.pool_size,
loop=asyncio.get_event_loop()
)
# 获取一个连接
async def acquire(self):
return await self.pool.acquire()
# 释放一个连接
async def release(self, conn):
self.pool.release(conn)
# 关闭连接池
async def close(self):
self.pool.close()
await self.pool.wait_closed()
print('close pool')
async def worker(semaphore, id, pool):
async with semaphore:
conn = await pool.acquire()
async with conn.cursor() as cursor:
await cursor.execute(sql)
rows = await cursor.fetchall()
print(rows)
print(f"Worker {id} finished")
await asyncio.sleep(1)
await pool.release(conn)
# 主函数
# 建立连接池,设置连接池大小为5,并发调用4个协程,获取查询
async def main():
pool = MysqlAsyncPool(5)
await pool.create_pool()
semaphore = asyncio.Semaphore(4) # 当并发数大于连接池大小时,程序回阻塞,直到有连接释放
tasks = []
for i in range(20):
task = asyncio.create_task(worker(semaphore, i, pool))
tasks.append(task)
await asyncio.gather(*tasks)
await pool.close()
# 有效使用连接池,有利于提高程序的性能,减少数据库连接的开销,但连接池的大小需要根据实际情况进行设置,需考虑服务器的负载
if __name__ == '__main__':
asyncio.run(main())
es
Elasticsearch(简称ES)是一个基于Lucene的分布式搜索引擎,它提供了全文检索、结构化检索、数据分析等功能,并且支持实时数据处理和可扩展性。ES的主要优势在于它的速度、强大的全文搜索能力和可扩展性,使得它成为了一个非常流行的搜索引擎和数据处理平台。
主要特点:
- 分布式架构:ES是一个分布式系统,可以在多台服务器上部署,以提高系统的性能和可用性。
- 实时搜索:ES支持实时数据处理,可以在毫秒级别内搜索最新的数据。
- 全文检索:ES提供了强大的全文搜索能力,支持各种查询类型、自动补全、拼写纠错等功能。
- 数据聚合:ES支持数据聚合和分析,可以方便地对大量数据进行统计和分析。
- 可扩展性:ES支持水平扩展和自动分片,可以轻松地扩展集群规模和数据量。
使用场景: - 搜索引擎:ES可以用作内部搜索引擎或外部搜索引擎,例如企业内部知识库搜索、电子商务网站搜索等。
- 实时数据处理:ES可以处理实时数据,例如日志分析、实时监控等。
- 数据聚合和分析:ES支持聚合查询和数据分析,可以用于数据仓库、BI分析等。
- 网站搜索优化:ES可以用于网站SEO优化,例如站内搜索、关键词排名监控等。
基础es CURD语法 ----->es增删改查
其中,index_name是索引的名称,doc_id是文档的唯一标识符,field1和field2是文档中的字段名,value1和value2是对应的字段值。在查询中,match是一种查询类型,它会在指定字段中查找包含指定关键字的文档。
POST /index_name/_doc # 增
{
"field1": "value1",
"field2": "value2",
...
}
DELETE /index_name/_doc/doc_id # 删
PUT /index_name/_doc/doc_id # 改
{
"doc": {
"field1": "new_value1",
"field2": "new_value2",
...
}
}
GET /index_name/_search # 查
{
"query": {
"match": {
"field1": "value1"
}
}
}
python操作es
# coding=utf-8
# python操作es的demo
# es链接字符串
es_url = "http://127.0.0.1:9200"
# es的index
es_index = "products"
# 查询测试
from elasticsearch import Elasticsearch
# 查询es索引内的数据
query_condition = {
"query": {
"match_all": {}
}
}
es = Elasticsearch(es_url, timeout=180,
max_retries=10, retry_on_timeout=True)
# res = es.search(index=es_index, body=query_condition)
# print(res)
# 查询结果
# {'took': 0, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 2, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'products', '_type': '_doc', '_id': '1', '_score': 1.0, '_source': {'productName': 'iPhone 12', 'productDescription': 'Apple手机'}}, {'_index': 'products', '_type': '_doc', '_id': '3', '_score': 1.0, '_source': {'doc': {'productDescription': '更新描述', 'productName': '小米 12'}}}]}}
# 插入测试
# doc = {
# "productName": "iPhone 14",
# "productDescription": "最新苹果手机",
# "productPrice": 5999
# }
# ins = es.index(index=es_index, body=doc)
# print(ins)
# 插入结果
# {'_index': 'products', '_type': '_doc', '_id': 'yyJ1LIcBu-S19F5IpqUM', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 14, '_primary_term': 1}
# 更新测试 ==>更新id为yyJ1LIcBu-S19F5IpqUM的数据,价格为4999
# doc_update = {
# "doc": {
# "productPrice":4999
# }
# }
# update_res = es.update(index=es_index, id="yyJ1LIcBu-S19F5IpqUM", body=doc_update)
# print(update_res)
# 更新结果
# {'_index': 'products', '_type': '_doc', '_id': 'yyJ1LIcBu-S19F5IpqUM', '_version': 2, 'result': 'noop', '_shards': {'total': 0, 'successful': 0, 'failed': 0}, '_seq_no': 18, '_primary_term': 1}
数据库读写代码集合
===>正在开发中