day21 python模块和包 及绝对导入和相对导入

day21 python模块和包 及绝对导入和相对导入
 
一.模块
    1.如何自己写一个模块
        可以是py文件
        也可以是dll文件(底层是c,但可以直接用)
        也可以是zip文件(可以直接使用)
import my_module
 
二.模块的导入: import    
    1.模块的导入
import my_module                            #导入模块时, 会执行模块里面的代码
print(my_module.name)
print(my_module.my_name())
    2.模块的导入: 命名空间
def my_name():                             #导入的模块和当前文件在不同的命名空间(而且导入能用被导入的内存空间, 而被导入的不能反向用导入的内存空间中的变量)
    return 'in practice s my_name'
print(my_name())
    3.import导入模块时发生了什么?
1.找到这个模块
2.判断这个模块是否被导入过了
3.1.如果没有被导入过
    创建一个属于这个模块的命名空间
    让模块的名字指向这个命令空间
    执行这个模块的代码
3.2.如果被导入过
    就不再重复导入
    4.如何判断模块是否被导入过了
import sys
print(sys.modules)
    5.1.为模块起别名 as: 别名可以用
import my_module as m                         #之前的原名字就不能用了(让my_module去找这个文件, 让m指向内存空间)
print(m.my_name())
print(my_module.name)
    5.2.别名, 原名都能用: 分别导入两次
import my_module                              #这样导入新别名和原来的名字都可以用
import my_module as m   
print(m.my_name())
print(my_module.name)
    5.3.别名用法: 当你导入的多个模块可能做相同事情的时候
def func(dic,flags = 'json'):
    if flags == 'json':
        import json as que
    if flags == 'pickle':
        import pickle as que
    return que.dump(dic)
    6.一行导入多个模块
import os, sys, time                            #逗号分隔, 但是不建议这样写: 若同时需导入内置模块, 第三方, 自定义.应该是这个顺序比较好
 
三.模块的导入: from import
    1.from 模块 import 变量名
from my_module import name
print(name)
    2.from 模块名 import 变量名: 的时候发生了什么
        (import了哪个变量就只能用哪个变量)
        (但是还是会执行模块中的所有代码)
1.找到要被导入的模块
2.判断这个模块是否被导入过
3.1.如果没被导入过
    创建一个属于这个模块的命名空间
    先执行这个文件中的代码
    然后找到你要导入的变量
    再给你要导入的变量(导入文件的内存中)创建一个引用,指向要导入的变量(被导入的文件的内存)
3.2.如果已经被导入过
    不再创建模块的内存空间, 也不在执行模块中的代码
    直接把你要导入的变量(导入文件的内存中)创建一个引用,指向要导入的变量(被导入的文件的内存)
    3.命名空间
name = 'change module name'     
print(name)
    4.为导入的名字起别名
from my_module import name as alias1, my_name as alias2
    5.一行导入多个模块
from my_module import name, my_name
    6.*和__all__的关系
from my_module import *         #说明你导入了模块中的所有的东西, 都可以直接用
print(name)
print(my_name())                #报错: 若你用*这样的方式导入时, 会找到被导入模块中变量 __all__ = ['name'] , 只能导入__all__中写的变量
 
from my_module import my_name   #__all__只能约束 * 的时候, 这样导入时不影响
print(my_name())
 
 
四.模块引用中的情况
    1.模块的循环引用
        一个纯的函数组成的多个模块之间, 不能形成循环引用: 设计程序时候要避免
    2.模块的加载与修改
import time
import my_module                #这个时候所有代码都执行完了
import importlib
 
time.sleep(20)                  #如果这个时间修改了文件中的内容, 那么你只是修改了文件, 而不是修改了内存
importlib.reload(my_module)     #这个是重新import了一遍, 代码重新执行一遍(正常人不用这个)
print(my_module.my_name())
    3.把模块当成脚本执行
        直接运行这个文件, 叫脚本: __name__ == '__main__'
        被导入执行, 叫模块: __name__ == '模块名'
import my_module                #内置的模块被导入时, 执行代码,并没有输出;  而我们自己的模块被导入时, 有打印东西, 不专业
 
import calculate
print(calculate.main('23+98*33'))
        #当成脚本时: 能自主完成交互
        #当成模块时: 需要被调用才能交互
        #在被导入的模块中 __name__ == '__main__' 才执行顶层函数
    4.模块的搜索路径
        当和被当做脚本执行的文件同目录下的模块:  可以直接被导入
        除此之外其他路径下的模块: 在被导入式需要自己修改sys.path列表
import sys
print(sys.path)
path = r'C:\Users\THINKPAD\PycharmProjects\s15\day01\bajie'
sys.path.append(path)
import a
 
五.包
    1.什么是包
        就是文件夹中有一个 __init__.py 文件
        是几个模块的集合
    2.从包中导入模块
        凡是导入带点的, 点的左边必须是一个包
        import
import glance.api.policy
import glance.api.policy as policy          #用的时候名字长, 搞个别名
 
glance.api.policy.get()
policy.get()
        from import
from glance.api import policy               #导入模块                   #from import时, import后面的东西不能有点
from glance.api.policy import get           #直接导入函数
policy.get()
get()
    3.直接导入一个包: 然后通过这个包可以用包里面的所有模块,需要设计__init__.py文件
        3.1.1.绝对导入
import glance               #导入一个包, 不意味着这个包下的文件能用
                            #导入一个包,发生了什么: 执行了包下面的 __init__.py文件
glance.api.policy.get()     #没有执行导入api, 那么我在__init__.py文件里导入api, 不就行了吗?
                            #不行, 因为import glance时候, glance执行__init__.py里面的 import api的时候, 用的还是执行glance时的sys.path
                            #这个时候如果sys.path没有api目录的路径, 那么就找不到api这个文件
 
如何解决: 
    在glance的__init__.py 文件里from glance import api
    在api的__init__.py 文件中from glance.api import policy
'''
glance\
|
|--api\
|   |
|   |--policy.py
|   |--versions.py
|   |--__init__.py:    from glance.api import policy    
|
|--cmd\
|   |
|   |--manager.py
|   |--__init__.py:    from glance.cmd import manager
|
|--db\
|   |
|   |--model.py
|   |--__init__.py:   from glance.db import model 
|
|--__init__.py:    from glance import api,cmd,db
                  
'''
import glance
glance.api.policy.get()
                            #那么通过这个方法, 就可以通过直接导入一个包的方法, 用这个包里面的所有东西
                            #绝对导入: 我认识这个路径, 那么我就可以从这个路径导入所有的文件
                            #缺点: 如果当前导入包的文件和被导入包的位置关系发生了变化,那么所有的__init__.py都要调整
        3.1.2:绝对导入:pycharm帮你做的事: 当你的文件要导入的包, 和你的文件不是平级的, 怎么办? 
                比如以上绝对导入在改位置时,这时pycharm会自动给你在__init__.py文件中改绝对的路径
 
        3.2.1.相对导入
import glance                     #glance的__init__.py:  from . import api  #api的__init__.py:  from . import policy
 
'''
glance\
|
|--api\
|   |
|   |--policy.py
|   |--versions.py
|   |--__init__.py:    from . import policy, versions
|
|--cmd\
|   |
|   |--manager.py
|   |--__init__.py:    from . import manager;     from ..api import policy     #想在manager中使用policy模块中的方法的时候
|
|--db\
|   |
|   |--model.py
|   |--__init__.py:   from . import model
|
|--__init__.py:    from . import api,cmd,db    
'''
glance.api.policy.get()
        3.2.2.相对导入: 如果改变了glance和导入文件的位置, 被放到了和导入文件同级的包upname里面
from upname import glance               #只要找到glance, 就可以直接使用, __init__.py中的相对导入不用改
glance.api.policy.get()
        3.2.3.相对导入: 注意事项
from . import api                      #文件中导入用的是相对 . 时, 文件本身不能被直接执行
                                       #必须放在一个包中, 被导入的调用才能正常使用
    4.总结:
        如果只是从包中导入模块, 那么我们不需要做任何多余的操作, 直接导入就好了
        如果我们希望导入包的时候,顺便把模块也导入进来, 那么需要用绝对导入,和相对导入
 
 
六.项目开发规范
'''
software\                    #项目名
|
|--bin\                      #脚本目录
|   |
|   |--start.py              -- 只放一个启动脚本
|
|--conf\                     #配置文件目录
|   |
|   |--config.ini            -- 比如你代码里的用到的文件名等变量,可以单独写到这个文件中
|   |--my_log_settings.py    -- 以后所有代码用到变量的值改动的时候, 都只需要在conf中修改, 不用改代码了
|   |--settings.py           -- 方便运维同学使用和维护
|
|--core\                     #核心代码目录
|   |
|   |--core.py              -- 如auth.py等代码
|  
|--db\                       #数据库目录
|   |    
|   |--bajie_json           -- 用户信息啥的           
|   |--wukong_json
|   
|--lib\                      #库文件目录
|   |
|   |--read_ini.py          -- 别人开发好的功能, (不是内置的, 也不是第三方, 可能是你自己写的比较完善的,还和当前项目的相关性不大, 是个通用模块)
|   
|--log\                     #日志文件目录
    |
    |--all.log              -- 记录日志
 
'''
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/aiaii/p/12190895.html