'''
序列化模块
'vbfjdbgvfdgvjbfdjgbvfd[' 是一个序列,序列化——转向一个字符串数据类型
序列——字符串
写文件 写字符串,数据存储
网络上传输 ,传bytes,字典、列表 ——字符串——bytes
数据类型——字符串的过程 ,序列化
从字符串——数据类型 反序列化

json 模块
通用的序列化格式,只有尽量少的数据类型能够通过json转化为字符串
pickle 模块
所有的python中的数据类型都可以转化为字符串类型
pickle只有python能理解,反序列化依赖代码,常用于人物游戏,必须双方的内存中得有相同的包
shelve模块
序列化句柄
使用句柄直接操作,方便 ,
'''


json模块,对数据格式要求严格

本身只认出一个'{"kkk:"}', dumps序列化方法,loads反序列化方法

from time import sleep
import time as t
import sys
import demo
import shelve
# from os import close
import time
import pickle
import json
dic = {'k1', 'v1'}
print(type(dic))
str_d = json.dumps(dic)
print(type(str_d), str_d)
dic_d = json.loads(str_d)
print(type(dic_d), dic_d) # 反序列化
# 只有数字、字符串、列表、字典、元组被转为列表, 这些是可序列化和反序列化的
# json模块,dump和load,和文件相关的操作
dic = {1: 'a', 2: 'b'}
# with open("fff", 'w',encoding='utf-8') as f:
f = open('fff', 'w', encoding='utf-8')
json.dump(dic, f) # 先序列化,再传进文件,给文件句柄
f.close()
f = open('fff')
res = json.load(f)
f.close()
print(type(res), res)


当传入的文件有中文时

做法一,推荐

dic = {1: '中国', 2: 'b'}
# with open("fff", 'w',encoding='utf-8') as f:
f = open('fff', 'w', encoding='utf-8')
json.dump(dic, f, ensure_ascii=False) # 先序列化,再传进文件,给文件句柄,true为bytes类型写进去,不影响读
f.close()
f = open('fff', encoding='utf-8')
res = json.load(f)
f.close()
print(type(res), res)


怎么读取决于怎么写,json模块用dump和load只能一次性的写进去,读出来

做法二

f = open('file')
lis = []
for line in f:
dic = json.loads(line.strip())
lis.append(dic)
f.close()
print(lis)


pickle模块

dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
str_dic = pickle.dumps(dic)
print(str_dic) # 结果是bytes数据类型
dic2 = pickle.loads(str_dic)
print(dic2)
struct_time = time.localtime(100000000)
print(struct_time)
with open('pickle_file', 'wb') as f:
pickle.dump(struct_time, f) # dump需要用wb方式写入
with open('pickle_file', 'rb') as f:
struct_time2 = pickle.load(f) # 需要以rb的方式load
print(struct_time2.tm_year)
# 可以分布的dump和load,json是一下子load出来
# pickle操作bytes数据类型


shelve模块,使用较少

f = shelve.open('shelve_file')
f['key'] = {'int': 10, 'float': 9.5,
'string': 'Sample data'} # 直接对文件句柄操作,就可以存入数据
f.close()
f1 = shelve.open('shelve_file')
exiting = f1['key'] # 去除数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(exiting)


shelve模块只读问题

# 虽然以只读的当时打开,但是仍然可以写入文件,此处的writeback = True可以再关闭文件指针后使文件的修改保存
f = shelve.open('shelve_file', flag='r')
existing = f['key'] # shelve会增加内存消耗和额外的等待时间
print(existing)
f.close()


一个文件就是一个模块

demo.py

# !/usr/bin/env python
# -*- coding:utf8 -*-


def read1():
print('in demo.py')

def read():
print('in read1')


if __name__ == 'main':
read1()
# __all__ = ['money'],和import *关联


原理机制

demo.read()
# 找到这个模块
# 创建这个模块的命名空间
# 把文件中的名字都放到内存空间里
print(sys.modules.keys())
# 当导入一个模块时,会先查询是否在sys.modules中,如果已经存在,就不再重复导入
# 没有被导入就一句sys.path路径寻找模块,找不到就报错
# 给模块取别名
print(t.time())
# 别名可以帮助当两个包分别由处理不同格式的相同内容的函数时
# 起别名可以更加方便地使用这两个包中的两个方法,提高代码的兼容性。


例子

'''
第一个例子
oracle
myaql
import oracle
import mysql
连接数据库,oracle.connect,mysql.connect
登录认证,增删改查,关闭数据库
'''
'''
第二个例子
if file_format == 'xml':
import xmlreader as reader
elif file_format == 'csv':
import csvreader as reader
data = reader.read_date(filename)
重命名之后只有重命名的名字可以使用,原来的包的名字不能使用
'''


其他

'''
不推荐 import time, sys,os的写法
先导内置模块,再导拓展的,再导自定义的
有的编译器自定义模块认为根节点是包的路径
sleep(1)
对于导包,from demo import 变量名,如果本地函数和变量名一样,本地的会覆盖导入的
from demo import money,read()仍从源文件中读取money的值
from demo import * 能修改demo文件中的变量
import
模块名.变量名 和本地文件的变量名完全不冲突
from import
直接使用变量名就可以完成操作
如果本文件中有相同的变量名会冲突
支持重命名,import * 和__all__=[]连用,没有会导入所有的名字
包,一大堆模块的集合
模块中有个__name__的方法,当我们直接执行这个模块时,__name__=='main',引入时是__name__== '模块名'
'''