python:序列与模块
一,序列化模块
什么叫序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。
比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic)的方法,将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?eval官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
为什么要进行序列化
序列化的目的
1,json模块
Json模块提供了四个功能:dumps、dump、loads、load
1)dumps和loads
#json dumps序列化方法 loads反序列化方法
dic = {1:"a",2:'b'}
print(type(dic),dic)
import json
str_d = json.dumps(dic) # 序列化
print(type(str_d),str_d)
# '{"kkk":"v"}'#注意:kkk用" "(双引号引起来了)
dic_d = json.loads(str_d) # 反序列化
print(type(dic_d),dic_d)
'''
<class 'dict'> {1: 'a', 2: 'b'}
<class 'str'> {"1": "a", "2": "b"}
<class 'dict'> {'1': 'a', '2': 'b'}
'''
dumps和loads
dumps是序列化方法,loads反序列化方法
2)dump与load
import json
# json dump load
dic = {1:"a",2:'b'}
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)
'''
<class 'dict'> {'2': 'b', '1': 'a'}
'''
dump和load
3)dumps、loads与dump、load的区别
有s的直接在内存操作数据类型,没有s的方法是直接在文件里读写数据类型。
dump需要需要有文件句柄,load不能进行多次load。
4)ensure_ascii关键字参数
import json
f = open('file','w')
json.dump({'国籍':'中国'},f)
ret = json.dumps({'国籍':'中国'})
f.write(ret+'\n')
json.dump({'国籍':'美国'},f,ensure_ascii=False)
ret = json.dumps({'国籍':'美国'},ensure_ascii=False)
f.write(ret+'\n')
f.close()
ensure_ascii关键字参数
5)json格式化输出
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)
json格式化输出
2,pickle
import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic) #一串二进制内容 dic2 = pickle.loads(str_dic)
print(dic2) #字典
2)分步dump与load
dump和load必须用wb和rb打开
import time
struct_time1 = time.localtime(1000000000)
struct_time2 = time.localtime(2000000000)
f = open('pickle_file','wb')
pickle.dump(struct_time1,f)
pickle.dump(struct_time2,f)
f.close()
f = open('pickle_file','rb')
struct_time1 = pickle.load(f)
struct_time2 = pickle.load(f)
print(struct_time1.tm_year)
print(struct_time2.tm_year)
f.close()
分步dump和分步load
3,shelve
import shelve
f = shelve.open('shelve_file')
f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接对文件句柄操作,就可以存入数据
f.close()
import shelve
f1 = shelve.open('shelve_file')
existing = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)
二、模块
1,什么是模块?
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
2,import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
3,import
1)示例文件:自定义模块my_module.py,文件名my_module.py,模块名my_module
#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
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句)
#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
'''
#调用了多次但是只打印了一个结果
我们可以从sys.modules中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
2)每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
#测试一:money与my_module.money不冲突
#demo.py
#my_module中:from the my_module.py
import my_module
money=10
print(my_module.money) '''
执行结果:
from the my_module.py
'''
3)测试二:read1与my_module.read1不冲突
#测试二:read1与my_module.read1不冲突
#demo.py
#my_module:
#print('from the my_module.py')
#def read1():
# print('money 1000')
import my_module
def read1():
print('========')
my_module.read1() '''
执行结果:
from the my_module.py
my_module->read1->money 1000
'''
4)测试三:执行my_module.change()操作的全局变量money仍然是my_module中的
#测试三:执行my_module.change()操作的全局变量money仍然是my_module中的
#demo.py
import my_module
money=1
my_module.change()
print(money) '''
执行结果:
from the my_module.py
'''
5)
总结:首次导入模块my_module时会做三件事:
1.为源文件(my_module模块)创建新的名称空间,在my_module中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2.在新创建的命名空间中执行模块中包含的代码,见初始导入import my_module
导入模块时到底执行了什么? 事实上函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看
3.创建名字my_module来引用该命名空间
1 这个名字和变量名没什么区别,都是‘第一类的’,且使用my_module.名字的方式可以访问my_module.py文件中定义的名字,my_module.名字与test.py中的名字来自两个完全不同的地方。
6)为模块名起别名,相当于m1=1;m2=m1
import my_module as sm
print(sm.money)
示范用法一:
有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
#mysql.py
def sqlparse():
print('from mysql sqlparse')
#oracle.py
def sqlparse():
print('from oracle sqlparse') #test.py
db_type=input('>>: ')
if db_type == 'mysql':
import mysql as db
elif db_type == 'oracle':
import oracle as db db.sqlparse()
复制代码
4,from ... import...
from my_module import read1,read2
这样在当前位置直接使用read1和read2就好了,执行时,仍然以my_module.py文件全局名称空间
from demo import money,read
print(money)
read()
money = 200
read()
#测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
#demo.py
from my_module import read1
money=1000
read1()
'''
执行结果:
from the my_module.py
spam->read1->money 1000
''' #测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
#demo.py
from my_module import read2
def read1():
print('==========')
read2() '''
执行结果:
from the my_module.py
my_module->read2 calling read1
my_module->read1->money 1000
'''
这样在当前位置直接使用read1和read2就好了,执行时,仍然以my_module.py文件全局名称空间
如果当前有重名read1或者read2,那么会有覆盖效果
#测试三:导入的函数read1,被当前位置定义的read1覆盖掉了
#demo.py
from my_module import read1
def read1():
print('==========')
read1()
'''
执行结果:
from the my_module.py
==========
'''
需要特别强调的一点是:python中的变量赋值不是一种存储操作,而只是一种绑定关系,如下:
from my_module import money,read1
money=100 #将当前位置的名字money绑定到了100
print(money) #打印当前的名字
read1() #读取my_module.py中的名字money,仍然为1000 '''
from the my_module.py
my_module->read1->money 1000
'''
1)as
也支持as
from my_module import read1 as read
2)也支持多行输入
from my_module import (read1,
read2,
money)
5,把模块当做脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
def fib(n):
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print() if __name__ == "__main__":
print(__name__)
num = input('num :')
fib(int(num))
6模块搜索路径
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
在第一次导入某个模块时(比如my_module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。
所以总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。
模块总结:
1,import和from import都支持as重命名,都支持多名字的导入
2,一个模块被import导入之后,并不会再次被导入。因为sys.mouldes记录了所有被导入的模块
3,sys.path记录了导入模块的时候寻找的所有路径
4,模块就是一个py文件
5,__all__必须与*连用
python:序列与模块的更多相关文章
- python 序列话模块 常用
什么是序列化? 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flatte ...
- 学习PYTHON之路, DAY 6 - PYTHON 基础 6 (模块)
一 安装,导入模块 安装: pip3 install 模块名称 导入: import module from module.xx.xx import xx from module.xx.xx impo ...
- #python基础学习模块:marshal 对象的序列化
#标准库地址:https://docs.python.org/2/library/marshal.html"""有时候,要把内存中一个对象持久化保存磁盘或者序列化二进制流 ...
- [Python笔记][第二章Python序列-复杂的数据结构]
2016/1/27学习内容 第二章 Python序列-复杂的数据结构 堆 import heapq #添加元素进堆 heapq.heappush(heap,n) #小根堆堆顶 heapq.heappo ...
- [Python笔记][第二章Python序列-tuple,dict,set]
2016/1/27学习内容 第二章 Python序列-tuple tuple创建的tips a_tuple=('a',),要这样创建,而不是a_tuple=('a'),后者是一个创建了一个字符 tup ...
- Python序列类型
Python序列类型 序列:字符.列表.元组 所有序列都支持迭代 序列表示索引为非负整数的有序对象集合 字符和元组属于不可变序列,列表可变 1)字符 字符串字面量:把文本放入单引号.双引号或三引号中: ...
- Python第八天 模块 包 全局变量和内置变量__name__ Python path
Python第八天 模块 包 全局变量和内置变量__name__ Python path 目录 Pycharm使用技巧(转载) Python第一天 安装 shell 文件 Pyt ...
- 周末班:Python基础之模块
什么是模块 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写 ...
- Python学习——python的常用模块
模块:用一堆代码实现了某个功能的代码集合,模块是不带 .py 扩展的另外一个 Python 文件的文件名. 一.time & datetime模块 import time import dat ...
- 【转】python之random模块分析(一)
[转]python之random模块分析(一) random是python产生伪随机数的模块,随机种子默认为系统时钟.下面分析模块中的方法: 1.random.randint(start,stop): ...
随机推荐
- Manacher算法(马拉车)
学习博客:https://www.cnblogs.com/love-yh/p/7072161.html 首先,得先了解什么是回文串(我之前就不是很了解,汗).回文串就是正反读起来就是一样的,如“abb ...
- (转)Python之文件读写
Python之文件读写 原文:https://www.cnblogs.com/huilixieqi/p/6494891.html 本节内容: I/O操作概述 文件读写实现原理与操作步骤 文件打开模式 ...
- java连接redis使用jedis带密码
一.引入jedis的Maven配置文件 <!-- redis连接客户端jedis --> <dependency> <groupId>redis.clients&l ...
- 精选9个值得学习的 HTML5 效果
此文转自:http://www.cnblogs.com/lhb25/p/9-html5-effects.html,仅供本人学习参考,版权归原作者所有! 精选9个值得学习的 HTML5 效果[附源码] ...
- js中函数带不带var的本质区别是什么
本质区别是:带var的是定义,属于statement:不带var的是赋值,属于expression.不带var时,解释器认为变量已经定义过了,会在函数中找相应的定义,如果找不到,就会认为变量是在外一层 ...
- 2018上半年DDoS攻击报告:流量峰值达1.7Tbps
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 2018年上半年DDoS攻防仍如火如荼发展,以IoT设备为反射点的SSDP反射放大尚未平息,Memcached DDoS又异军突起,以最高可 ...
- ubuntu命令行添加拥有管理员权限新用户
最近买了个服务器,只有一个root用户,天天登录挺不方便的,所以想要新建用户;之前在本地都是用界面话新建的用户,这次记录一下学习命令行新建用户的过程: 第一步 : # sudo adduser zhq ...
- 【转】常用的邮箱服务器(SMTP、POP3)地址、端口
gmail(google.com)POP3服务器地址:pop.gmail.com(SSL启用 端口:995)SMTP服务器地址:smtp.gmail.com(SSL启用 端口:587) 21cn.co ...
- 安卓API版本
- SQL 表定时同步
1.创建存储过程 create proc [dbo].[sync_calendar] as truncate table dbo.CalendarEvents insert into Calendar ...