序列化
序列化:将原本的字典、列表等内容转换成字符串的过程就叫做序列化
序列化的目的:
1.以某种存储形式使自定义对象持久化
2.将对象从一个地方传递到另一个地方
3.使程序更具维护性
序列化:从数据类型 --> 字符串的过程
反序列化:从字符串 --> 数据类型的过程
用于序列化的模块:json、pickle、shelve
json:
通用的序列化格式,通过json,不同编程语言之间可以互相识别;
pickle:
pickle序列化的内容只有python能理解,且部分反序列化依赖python代码;
所有的python中的数据类型都可以转化成字符串形式
shelve:
序列化句柄
使用句柄直接操作,非常方便
json模块
提供了四个功能:dumps、dump、loads、load
可序列化数据类型:数字、字符串、列表、字典、元组(通过转换成列表再序列化)
import json dic = {1: "a", 2: "b"} dic_d = json.dumps(dic) # 序列化 print(dic_d, type(dic_d)) # {"1": "a", "2": "b"} <class 'str'> dic_l = json.loads(dic_d) # 反序列化 print(dic_l, type(dic_l)) # {"1": "a", "2": "b"} <class 'str'>
dump、load:必须打开一个文件再操作,一次性写进去,一次性读出来
dic = {1: "a", 2: "b"} with open("1.txt", "w", encoding="utf-8") as f: json.dump(dic, f) with open("1.txt", "r", encoding="utf-8") as f: ret = json.load(f) print(ret, type(ret)) # {'1': 'a', '2': 'b'} <class 'dict'>
对于中文:序列化时添加参数 ensure_ascii=False
dic = {1: "你好", 2: "世界"} ret = json.dumps(dic, ensure_ascii=False) print(ret, type(ret)) # {"1": "你好", "2": "世界"} <class 'str'> with open("1.txt", "w", encoding="utf-8") as f: json.dump(dic, f, ensure_ascii=False) with open("1.txt", "r", encoding="utf-8") as f: ret = json.load(f) print(ret, type(ret)) # {'2': '世界', '1': '你好'} <class 'dict'>
pickle模块
用于python特有的类型和python的数据类型间进行转换
pickle模块提供了四个功能:dumps/dump(序列化,存)、loads(反序列化,读)、load(不仅可以序列化字典、列表...可以把python中任意的数据类型序列化)
import pickle dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} str_dic = pickle.dumps(dic) print(str_dic) # bytes数据类型 dic2 = pickle.loads(str_dic) print(dic2) #{'k3': 'v3', 'k2': 'v2', 'k1': 'v1'}
import pickle import time struct_time = time.localtime(1000000000) print(struct_time) #time.struct_time(tm_year=2001, tm_mon=9, tm_mday=9, tm_hour=9, tm_min=46, tm_sec=40, tm_wday=6, tm_yday=252, tm_isdst=0) f = open('pickle_file', 'wb') pickle.dump(struct_time, f) f.close() f = open('pickle_file', 'rb') struct_time2 = pickle.load(f) print(struct_time2.tm_year) #2001
shelve模块:
import shelve f = shelve.open('shelve_file') f['key'] = {'int': 10, 'float': 9.5, 'string': 'Sample data'} # 直接对文件句柄操作,就可以存入数据 f.close() f1 = shelve.open('shelve_file') existing = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错 f1.close() print(existing) #{'string': 'Sample data', 'int': 10, 'float': 9.5}
模块的导入
模块的导入顺序:
内置模块
扩展模块
自定义模块
我们可以从sys.modules中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入,所以sys.modules决定了模块不会被重复导入
import sys print(sys.modules) # 结果是一个字典
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
当要导入模块时,就依据sys.path路径寻找需要导入的模块
import sys print(sys.path) #['E:\study_python', 'E:\study_python', 'E:\study_python\venv\Scripts\python35.zip', 'C:\Python35\DLLs', 'C:\Python35\lib', 'C:\Python35', 'E:\study_python\venv', 'E:\study_python\venv\lib\site-packages', 'E:\study_python\venv\lib\site-packages\setuptools-39.1.0-py3.5.egg', 'E:\study_python\venv\lib\site-packages\pip-10.0.1-py3.5.egg', 'D:\PyCharm201814\helpers\pycharm_matplotlib_backend']
# 导入的函数func,会被当前位置定义的read覆盖 from demo import func def func(): print("本地的func") func() # 本地的func
from...import *(这种方式非常不安全,慎用)
#demo里的代码如下: def read(): print("demo里的read") money = 100 #money没有使用demo里的值,而是使用了当前名称的值,所以非常不安全,慎用*这种导入模式 from demo import * money = 200 print(money) #200 --> 模块里的money方法将永远被覆盖 read() #demo里的read #而 import demo 不会出现这种情况,因为要使用money,就得用demo.money格式 import demo money = 200 print(money) #200 --> 当前的值 print(demo.money) #100 --> 模块的值
from...import * 模式中的 __all__ 的作用,只有带 * 这种模式才会有 __all__
# demo.py __all__ = ["func1", "func2"] def func1(): print("func1") def func2(): print("func2") ########################################
# test.py # 然后使用 from demo import * 就只能导入 func1 和 func2 方法啦 from demo import * func1() # func1 func2() # func2
如果demo.py中的名字前加 _ ,如_func1,则采用 from demo import * 时,_func1 不能被导入
import 与 from...import... 区别
import 导入模块格式: import 模块名 如何使用:模块名.变量名 和本文件中的变量名完全不冲突 import 模块名 as 自定义模块名 import 模块名1,模块名2 导入多个模块 from ... import ... 导入模块格式: from 模块名 import 变量名 如何使用:直接操作"变量名" 如果本文件中有相同的变量名会发生冲突 from 模块名 import 变量名 as 自定义变量名 from 模块名 import 变量名1,变量名2 从同一个模块导入多个功能 from 模块名 import * 将模块中的所有变量名都导入进来,但是那些由单一下划线 _开头的名字不在此例;大多数情况下,python程序员不使用这种方法,因为引入其他来源的命名,很可能覆盖了已有的定义 如果本文件中有相同的变量名会发生冲突
__name__ 属性
一个模块被另一个程序第一次引入时,其主程序将运行;如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用 __name__ 属性来使该程序块仅在该模块自身运行时执行。
# demo.py if __name__ == "__main__": print("程序自身在运行") else: print("我来自另一模块")
运行结果:
import demo # 我来自另一模块
demo.py # 程序自身在运行