python学习day20 序列化模块 模块的导入
http://www.cnblogs.com/Eva-J/articles/7228075.html#_label9
序列化模块
为什么要序列化?
数据存储
网络上传输的时候
从数据类型 --> 字符串的过程 序列化
从字符串 --> 数据类型的过程 反序列化
json --通用的序列化格式
通用的序列化格式
只有很少的一部分数据类型能够通过json转化成字符串
dump 和文件有关
不能load多次
pickle
所有的python中的数据类型都可以转化成字符串形式
pickle序列化的内容只有python能理解
且部分反序列化依赖python代码
dump和load的时候,文件是rb或者wb打开的
shelve
比较新
序列化句柄
使用句柄直接操作,非常方便
json
数字 字符串 列表 字典 元组
dumps -- 序列化
loads --- 反序列化
直接在内存中执行
import json dic = {1:"a",2:'b'} print(type(dic),dic) str_d = json.dumps(dic) # 序列化 print(type(str_d),str_d) # str {"k": "v1"} 双引号 # '{"kkk":"v"}' dic_d = json.loads(str_d) # 反序列化 print(type(dic_d),dic_d) # 元组序列化后变成列表字符化,反序列化后还是列表 # 集合不能序列化
dump load
可以写入文件
import json f = open('json_file','w') dic = {'k1':'v1','k2':'v2','k3':'v3'} json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件 f.close() f = open('json_file') dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回 f.close() print(type(dic2),dic2)
import json f = open('file','w') json.dump({'国籍':'中国'},f) ret = json.dumps({'国籍':'中国'}) f.write(ret+'\n') json.dump({'国籍':'美国'},f,ensure_ascii=False) # json中的是汉字 不加的话会是bytes编码 ret = json.dumps({'国籍':'美国'},ensure_ascii=False) f.write(ret+'\n') f.close()
格式化输出:
import json data = {'username':['李华','二愣子'],'sex':'male','age':16} json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False) print(json_dic2) # Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key # ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json # separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 # sort_keys:将数据根据keys的值进行排序。
模块
模块导入顺序:
内置模块
扩展模块 比如django
自定义模块
模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看
为了防止重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句。
定义一个模块:
#my_module.py print('from the my_module.py') money=1000 def read1(): print('my_module->read1->money',money) def read2(): print('my_module->read2 calling read1') read1() def change(): global money money=0
我们可以从sys.modules中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
先从sys.modules里查看是否已经被导入
如果没有被导入,就依据sys.path路径取寻找模块
找到了就导入
创建这个模块的命名空间
执行文件,把文件中的名字都放到命名空间里
#demo.py import my_module #只在第一次导入时才执行my_module.py内代码,此处的显式效果是只打印一次'from the my_module.py',当然其他的顶级代码也都被执行了,只不过没有显示效果. import my_module import my_module import my_module ''' 执行结果: from the my_module.py '''
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
- 使用import demo导入模块,会创建一个独立的命名空间,里面的所有函数都被导入进来,再定义一个和demo中函数名一样的函数,就无效
- 使用from...import...导入,再定义一个和demo中函数名一样的函数,导入的函数就被覆盖
from my_module import * 把my_module中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。
在my_module.py中新增一行,__all__只和from...import* 关联
__all__=['money','read1'] #这样在另外一个文件中用from my_module import *就这能导入列表中规定的两个名字
import...
import # 1 import 模块名 模块名.变量名 和本文件中的变量名完全不冲突 # 2 import...as.. import 模块名 as 重命名的模块名 : 提高代码的兼容性 # 3 导入多个模块 import 模块1,模块2
from...import...
from import # 1 from 模块名 import 变量名 # 直接使用 变量名 就可以完成操作 # 如果本文件中有相同的变量名会发生冲突 # 2 from 模块名 import 变量名字 as 重命名变量名 # 3 from 模块名 import 变量名1,变量名2 # 4 from 模块名 import * # 将模块中的所有变量名都放到内存中 # 如果本文件中有相同的变量名会发生冲突 # 5 from 模块名 import * 和 __all__ 是一对 # 没有这个变量,就会导入所有的名字 # 如果有all 只导入all列表中的名字
重要! 把模块当脚本运行
我们可以通过模块的全局变量__name__来查看模块名:
在模块中 有一个变量__name__,
当我们直接执行这个模块的时候,这个模块中__name__ == '__main__'
当我们执在其他模块中引用这个模块的时候,这个模块中的__name__ == '模块的名字',if __name__ =='__main__'下的内容不会执行
if __name__ =='__main__':
为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度。python解释器会在__pycache__目录中下缓存每个模块编译后的版本,格式为:module.version.pyc。通常会包含python的版本号。例如,在CPython3.3版本下,my_module.py模块会被缓存成__pycache__/my_module.cpython-33.pyc。这种命名规范保证了编译后的结果多版本共存。