zoukankan      html  css  js  c++  java
  • 模块之序列化模块和包

    一.序列化模块

    1.序列化——将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化(把要传输的和要存储的内容 转换成 字符串)
    反序列化--字符串 转换回 要传输和存储的内容

    eval:可以将str类型转换为其不带“”的类型,但不推荐用eval方法来进行反序列化操作的原因:
    如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
    而使用eval就要担这个风险。

    2.序列化只有两种作用:

    1.网络传输:能在网络上传输的只能是bytes和字符串

     2.数据持久化 - 写在文件里

    不使用模块进行序列化和反序列化操作
    dic={'name':'jerd','age':18}
    a=str(dic)
    print(a,type(a))   #序列化{'name': 'jerd', 'age': 18} <class 'str'>
    print(eval(a),type(eval(a))) #反序列化{'name': 'jerd', 'age': 18} <class 'dict'>
    View Code

    3.Json模块提供了四个功能:dumps、dump、loads、load

    3.1dumps和loads 进行网络传输
    #3.1.1json转换完的字符串类型的字典中的字符串是由""表示的
    import json
    dic={'name':'jerd','age':18}
    ret=json.dumps(dic)
    print(ret,type(ret)) #{"name": "jerd", "age": 18} <class 'str'>
    #3.1.2要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
    print(json.loads(ret),type(json.loads(ret))) #{'name': 'jerd', 'age': 18} <class 'dict'>
    #字符串类型的字典中的字符串必须由''表示时
    dic={'name':'jerd','age':18}
    ret=str(dic)  #{'name': 'jerd', 'age': 18} <class 'dict'>
    print(json.loads(ret),type(json.loads(ret))) #son.decoder.JSONDecodeError:
    3.1.3处理嵌套的数据类型
    import json
    list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
    str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型
    print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
    list_dic2 = json.loads(str_dic)
    print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]
    3.2dump load 用在文件操作数据类型的序列化与反序列化上
    import json
    dic={'name':'jerd','age':18}
    with open("ban","w",encoding="utf-8") as f: #序列化
        json.dump(dic,f)
        #load 的参数为句柄
    with open("ban", encoding="utf-8") as f:  # 反序列化
        a=json.load(f)
        print(a,type(a))  #{'name': 'jerd', 'age': 18} <class 'dict'>
    #文件中有多行内容时,进行反序列化时 loads也只能一行一行的操作
    import json
    with open("ban", encoding="utf-8") as f:
    #不可json.loads(f.read())
        for i in f:
            a=json.loads(i)
            print(a,type(a))  #{'name': 'jerd', 'age': 18} <class 'dict'> [18, 52, 'sdc'] <class 'list'>
    3.3ensure_ascii关键字参数
    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)
    with open('ban','w',encoding='utf-8') as f:
        json.dump(data,f,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False)
    with open('ban', 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False)
    with open('ban','r',encoding='utf-8') as f:
         print(json.load(f))
    View Code

    4.pickle,用于bytes 和 python的数据类型间进行转换

    4.1 dumps 和loads
    import pickle
    data = {'username':['李华','二愣子'],'sex':'male','age':16}
    ret = pickle.dumps(data)
    print(ret)   #一串二进制内容
    print(pickle.loads(ret)) #{'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16}
    4.2 dump 和load 对文件操作要用rb或wb
    import pickle
    data = {'username':['李华','二愣子'],'sex':'male','age':16}
    with open('ban','wb') as f:
        pickle.dump(data,f)
        pickle.dump(data, f)
    with open('ban','rb') as f:
        print(pickle.load(f))  #{'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16}
        print(pickle.load(f))
    4.3 pickle的特点
    1.pickle模块 dumps之后是bytes
    2.pickle模块 dump之后的内容在文件中是乱的
    3.pickle模块可以连续dump数据进入文件,然后连续load出来
    4.pickle可以任意的将python中的数据类型序列化  json只能对列表 字典 进行序列化
    ###json 和 pickle的不同##
    json是一种所有的语言都可以识别的数据结构。
    如果我们将一个字典或者列表序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
    但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
    所以,如果你序列化的内容是列表或者字典,推荐使用json模块
    View Code

    json 和 pickle的不同

    json是一种所有的语言都可以识别的数据结构。
    如果我们将一个字典或者列表序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
    但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
    所以,如果你序列化的内容是列表或者字典,推荐使用json模块

    5.shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似

    往文件中写入内容
    import shelve
    f = shelve.open('ban') #会自动建三个文件。如果“ban”这个文件已经存在,则会报错.写进去后内容时是乱的
    f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'}  #直接对文件句柄操作,就可以存入数据
    f.close()
    ##读取内容
    f=shelve.open("ban")
    excting=f["key"]
    f.close()
    print(excting)  #{'int': 10, 'float': 9.5, 'string': 'Sample data'}
    View Code

    二.模块

    1 什么是模块?

    模块 是一个py文件
    一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀

    2 为何要使用模块?

    如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,
    需要时就通过python test.py方式去执行,此时test.py被称为脚本script。我们不仅仅可以把这些文件当做脚本去执行,
    还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
    View Code

    3.import

    自定义模块my_module.py,文件名my_module.py,模块名my_module
    在my_module.py中写入
    print(666)
    money=100
    def func1():
    print("the money is:",money)
    print(777)

    3.1导入模块之后解释器做的事情:

    1.找到这个模块,判断这个模块是否被导入过,如果没有被导入过,就导入
    2.创建属于这个模块的命名空间
    3.执行这个模块中的代码,将模块中的名字加载到命名空间中
    对于模块来说 并不会重复导入   模块间的命名空间是独立的
    View Code

    3.2模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块

    它们只在模块名第一次遇到导入import语句时才执行。如print(666) print(777)就是可执行语句

    python的优化手段是:
    第一次导入后将模块名加载到内存,后续的import语句仅是对已经加载到内存中的模块增加了一次引用,不会再执行模块内的语句)
    import my_moudle 只在第一次导入时才执行my_module.py内代码,显示666 777
    import my_moudle 不再显示666 777
    #如果在my_moudle中加入func1()
    import my_moudle
    print(my_moudle.func1())
    #666 the money is: 100 777
    #the money is: 100 None

    3.2 import ... as .. 临时重命名

    对文件进行操作
    if file == 'txt':
    import txt as file
    elif file == 'doc':
    import doc as file
    f = file.open()
    f.close()

    3.3 import m1,m2,m3 导入多个模块,但提倡分开用import分别导入

    4. form *** import ***

    
    
    4.1 my_moudle里面的内容都执行,只是需要谁把谁放到内存中
    from my_moudle import func1 #666 777
    from my_moudle import func1  
    money=10
    print(func1())  #100 None
    #如果用import  my_moudle 调用func1
    import  my_moudle
    print(my_moudle.func1())
    4.2 导入多个模块,用逗号分开
    4.3改名 form my_moudle import func1 as func
    4.4 from my_moudle import *  #将模块my_module不是以下划线(_)开头的所有的名字都导入到当前名称空间。不建议使用
    from my_moudle import *
    print(money)
    print(func1())
    ###与import my_moudle区别是:在用func1时前者直接func1() 后者my_moudle.func1()
    4.5*和__all__配合使用 :my_moudle中加上__all__=['money']
    这样在另外一个文件中用from my_module import *就这能导入列表中money名字
    print(func1())  #NameError: name 'func1' is not defined
    View Code
    
    

    5.其他

    1.不允许循环导入 即两个模块a,b在a模块中import b ,再在b模块中import a
    2.模块一旦导入 发生改变也不会影响已经导入的内容
    import time, importlib
    import my_moudle
    time.sleep(20)
    #importlib.reload( my_moudle)
    my_moudle.func1() # 666 777 "the money is:",money 修改不会变
    3.我们可以通过模块的全局变量__name__来查看模块名:
    当做脚本运行:
    __name__ 等于'__main__'
    当做模块导入:
    __name__= 模块名 当moudle中只有print(__name__)时在moudle中执行显示main 用其他文件导入moudle时显示模块名moudle
    作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
    if __name__ == '__main__':
    在my-moudle中执行
    print(666)
    money=100
    def func1():
    print("the money is:",money)
    print(777)
    if __name__ == '__main__':
    print(__name__)
    func1() #会执行func1()
    在另一py中执行import my--moudle 不会执行func1()
    4.模块搜索路径
    模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
    import sys
    print(sys.path) #显示路径 第一个是本文件所在的路径 #['D:\lianxi\python\数据类型和函数', 'D:\lianxi', 'D:\python3.6\anzhaunghou\python36.zip',
    print(sys.path.pop(0)) #删除第一个路径
    print(sys.path.pop(0)) #再将路径删除
    print(sys.path) #['D:\python3.6\anzhaunghou\python36.zip'
    import my_moudle #ModuleNotFoundError 报错 module模块
    4.文件当做模块被执行后会编译成pyc文件,在以后使用模块后,会节省模块启动的时间 并没有缩减运行代码的时间
    不当模块用,就不会编译成pyc文件

     

    三.包

    1.包的基本知识:

    1.1凡是在导入语句中(而不是在使用时)遇到带点的,这是关于包才有的导入语法
    1.2包的本质就是一个包含__init__.py文件的目录。导入包本质就是在导入该文件
    1.3 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
    1.4创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块

     

    2.导入包时注意:

    2.1凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则
    2.2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类

    3.从包中导入:

    
    
    3.1 import 
    import glance.db.models
    glance.db.models.register_models('mysql')
    3.2 from ... import ...
    from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
    from glance.db import models
    models.register_models('mysql')
    from glance.db.models import register_models
    register_models('mysql')
    3.3__init__.py文件
    不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件这个文件可以为空,
    但是也可以存放一些初始化包的代码

    4.绝对导入和相对导入

    
    
    绝对导入:以glance作为起始
    相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
    在glance/api/version.py
    #绝对导入
    from glance.cmd import manage
    manage.main()
    #相对导入
    from ..cmd import manage
    manage.main()

    5.软件开发规范:一个包下一般含多个文件夹

    1.bin文件夹(里面有个start.py)
    2.conf(里面有个setting.py)
    3.core(里面放核心代码)
    4.db(普通文件)
    5.lib库
    6.log

     

     

     

     

     
     
     
     
     
  • 相关阅读:
    C语言和python分别计算文件的md5值
    C语言计算文件大小
    Linux内核源码下载
    Linux系统编程20_VFS虚拟文件系统
    Linux系统编程19_标准I/O
    C语言Review5_函数指针和数组指针
    C语言Review4_头文件引用符号的区别
    PDO之MySql持久化自动重连导致内存溢出
    小程序之app.json not found
    phpstorm之"Can not run PHP Code Sniffer"
  • 原文地址:https://www.cnblogs.com/zgf-666/p/8541127.html
Copyright © 2011-2022 走看看