当前位置: 首页 > article >正文

python如何通过json以及pickle读写保存数据

记录信息

比如说我写了这样一段程序,记录了爱吃的食物:

food_list = []

while True:
    c = input("输入1添加新的食物,输入2查询已添加的食物,输入exit退出:")
    if c == "1":
        new_food = input("输入你喜欢的食物:")
        food_list.append(new_food)
        print("添加成功!")
    elif c == "2":
        for i in food_list:
            print(i, end=" ")
        print()
    elif c == "exit":
        print("谢谢,下次再见!")
        break

但是,很快就会发现这样一个问题,当我们下次再运行程序的时候,上次输入的内容全都没了,怎么会这样呢?

原理其实很简单,在程序运行的时候,我们存储的信息放入了python的列表之中,这些信息是保存在内存之中的,当程序运行结束,这些信息就没了。

那么,如果我希望将输入保存起来,下次还能看到,该怎么办呢?这个时候,就需要将要保存的内容存储到文件了。

json存储数据

json介绍

json,全名:JavaScript Object Notation,是一种轻量级的数据交换格式,最初基于JavaScript,但是后来随着发展,现在几乎被所有编程语言支持。

json数据非常适合人类阅读和编写,也可以在网络应用中进行数据传输,当然也可以作为数据存储。最常见的json数据类型包括object(对象),以及array(数组)。

json对象:

{
  "name": "仙草",
  "age": 18,
  "isStudent": false
}

json数组:

["啃达鸡美食", "疯狂星期四", "可口可乐"]

对于python中的数据类型来说,列表会被保存为json数组,而字典会被保存为json对象。

json写入文件

import json

# 需要保存的数据
data = [1, 2, 3, 4, 5]

# 转为json数据
json_data = json.dumps(data)

# 写入文件
with open("record.json", "w") as f:
    f.write(json_data)

json文件读取

import json

with open("record.json", "r") as f:
    json_data = f.read()
    
data = json.loads(json_data)

为程序添加保存读取

import json

try:
    with open("food_list.json", "r") as file:
        food_list = json.load(file)
except FileNotFoundError:
    food_list = []

while True:
    c = input("输入1添加新的食物,输入2查询已添加的食物,输入exit退出:")
    if c == "1":
        new_food = input("输入你喜欢的食物:")
        food_list.append(new_food)
        print("添加成功!")

        with open("food_list.json", "w") as file:
            file.write(json.dumps(food_list))

    elif c == "2":
        for i in food_list:
            print(i, end=" ")
        print()
    elif c == "exit":
        print("谢谢,下次再见!")
        break

pickle序列化

pickle介绍

pickle可以对一个python对象进行二进制序列化以及反序列化,比起json,使用pickle的一个好处是,pickle可以保存任意一个python对象,例如类或者函数,但是json则不能直接这样做。

注意:pickle具有危险性,因此,不要加载你不信任的内容,必须使用可信任的数据。

pickle写入文件

import pickle

data = [1, 2, 3, 4, 5]

with open("data.pkl", "wb") as f:
    pickle.dump(data, f)

pickle文件读取

import pickle

with open("data.pkl", "rb") as f:
    loaded_data = pickle.load(f)
    
print(loaded_data)

pickle具有安全风险

在python的官方文档上,有这样一段重要提示:“如果解序化的数据是由手段高明的攻击者精心设计的,这种不受信任来源的pickle数据可以执行任意代码。”

很多人对此有一些困惑,真的有这么严重吗?答案是肯定的。假设,有这样一段恶意代码:

import pickle
import os

class Example:
    def __reduce__(self):
        return (os.system, ('echo "不能随便使用危险的代码!"',))

malicious_data = pickle.dumps(Example())

with open("malicious.pkl", "wb") as file:
    file.write(malicious_data)

此时, 当代码重新被加载的时候,就会执行恶意代码,调用系统命令。

import pickle

with open("malicious.pkl", "rb") as file:
    data = pickle.load(file)

安全使用pickle

一种安全使用自己生成的pickle的方法,是使用hmac对序列化的数据进行签名,下次使用的时候进行签名的认证,以保证当初生成的pickle没有被他人篡改。下面是一种可能的实现:

import pickle
import hmac
import hashlib


secret_key = b"your-secret-key"


def save_signed_pickle(data, file_path, key):
    # 使用pickle序列化数据
    serialized_data = pickle.dumps(data)

    # 生成签名
    signature = hmac.new(key, serialized_data, hashlib.sha256).digest()

    # 将签名和序列化数据一起保存到文件
    with open(file_path, "wb") as f:
        f.write(signature)
        f.write(serialized_data)


def load_signed_pickle(file_path, key):
    # 从文件加载数据并验证签名
    with open(file_path, "rb") as f:
        signature = f.read(32)  # 签名长度为32字节,因此恰好可以读取到签名
        serialized_data = f.read()

    # 重新计算签名并进行验证
    expected_signature = hmac.new(key, serialized_data, hashlib.sha256).digest()
    if hmac.compare_digest(signature, expected_signature):
        # 签名匹配,说明数据未被篡改,可以安全反序列化
        return pickle.loads(serialized_data)
    else:
        # 签名不匹配,数据可能已被篡改
        raise ValueError("Data integrity check failed!")


http://www.kler.cn/news/366658.html

相关文章:

  • ubuntu22.04安装qemu-9.1并在i.MX6上运行linux kernel 6.11
  • 改变组件默认上报事件的参数,添加额外参数
  • 代码随想录算法训练营第二十七天|Day27 贪心算法
  • 计算机网络:网络层 —— IPv4 地址与 MAC 地址 | ARP 协议
  • Ubuntu20.04系统安装opencv
  • Pyramidal Flow使用指南:快手、北大、北邮,开源可免费商用视频生成模型,快速上手教程
  • gin入门教程(9):路由分组与路由版本控制
  • MySQL 存储结构
  • 基于信号分解和多种深度学习结合的上证指数预测模型
  • 基于Multisim的音频放大电路设计与仿真
  • 软体机器人纤维:材料选择有讲究,热拉伸工艺来制造,多种功能应用
  • Spring Boot 配置文件(yml、properties | bootstrap、application)加载顺序
  • Linux基础命令(三)之 重定向操作符,管道符|,tee
  • 1. 路由定义
  • redis高级篇之skiplist跳表 第164节答疑
  • [网络协议篇] TCP协议一
  • git 安装
  • 导出BERT句子模型为ONNX并推理
  • axios直接上传binary
  • PHP 正则表达式 修正符【m s x e ? (?i)】内部修正符 贪婪模式 后向引用 断言【总结篇】
  • 【C++初阶】一文讲通C++内存管理
  • 力扣第 420 场周赛 3324. 出现在屏幕上的字符串序列
  • Chromium127编译指南 Windows篇 - 使用 GN 工具生成构建文件(六)
  • 【二轮征稿启动】第三届环境工程与可持续能源国际会议持续收录优质稿件
  • 代码随想录day11 栈与队列
  • Android静态变量中的字段被置空了