• Python模块调用


    目录

    1 模块

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

    把定义的函数、变量保存到文件中,通过Python test.py的方式执行,test.py就是脚本文件。程序功能越来越多,这些监本文件还可以当做模块导入其他的模块中,实现了重利用。

    import

    使用import的时候,想要使用spam下面的方法,必须使用spam.的方式

    import spam
    
    print(spam.money)
    spam.read1()
    spam.read2()
    spam.change()
    

    from… import …

    对比import spam,会将源文件的名称空间’spam’带到当前名称空间中,使用时必须是spam.名字的方式

    而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了、

    1.1 使用模块

    #spam.py
    print('from the spam.py')
    
    money=1000
    
    def read1():
        print('spam->read1->money',1000)
    
    def read2():
        print('spam->read2 calling read')
        read1()
    
    def change():
        global money   # 经过测试这个在执行这个脚本自身的时候,global是把money的值引过来了,然后再下面进行了修改,之后再打印就是0
        money=0
         print(money)  # 这里是有打印了下 主要 是在模块中的时候进行测试
    if __name__ == '__main__':
    # main()
    print("测试")  # 初始化执行的
    
    print(money)
    
    change()
    print(money)
    

    结果是:
    1000
    0
    0

    1.2 Python模块的导入

    python模块在导入的时候,防止重复导入,在第一次导入后,会加载到内存,在之后的调用都是指向内存

    #test.py
    import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
    import spam
    import spam
    import spam
    
    '''
    执行结果:
    from the spam.py
    '''
    

    从sys.module中找到当前已经加载的模块

    1.3 模块的名称空间

    每一个模块都是一个独立的名称空间,定义在这个模块总的函数会把模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突

    from spam import money, read1, read2,change  # 可以导入多个
    
    print(money)  # 引用的是change 中的money
    change()  # 这个是修改了的 只是在
    print(money)
    
    '''
    结果是:
    1000
    0
    1000
    '''
    

    1.4 导入模块的做的事情

    1. 为源文件(spam)创建新的名称空间,在spam中定义的函数和方法使用了global时,访问的就是这个名称空间。
    2. 在新创建的名称空间中执行模块中包含的代码
    3. 创建名字spam来引用该命名空间

    寻找的优先级:

    '''
    先从内存中寻找,sys.modules
    然后从内置的寻找(内建)
    从自己的路径中寻找 从sys.path中寻找
    '''
    

    2 from import

    2.1

    python中的变量赋值不是一种存储操作,而只是一种绑定关系

    from spam import money, read1, read2, change
    money = 100000000  # money现在是绑定到新的上
    print(money)  # 现在就有冲突了
    
    read1()
    read1 = 1111111
    read2()  # 这个不影响,从哪里调用,用哪里的
    

    2.2 from spam import *

    from spam import 把spam中所有的不是以下划线(_)开头的名字都导入到当前位置,大部分情况下我们的python程序不应该使用这种导入方式,因为你不知道你导入什么名字,很有可能会覆盖掉你之前已经定义的名字。而且可读性极其的差,在交互式环境中导入时没有问题。

    通常使用all=[‘money’,’read1’],这样引用spam的就只能用money和read1两种

    3 把模块当做脚本执行

    文件有两种应用场景,一种是当做脚本执行,一种是当做模块

    3.1 脚本执行

    spam文件执行的的时候

    print(__name__)
    结果是:
    '''
    __main__
    '''
    

    3.2 模块执行

    在test文件中导入import spam,打印的结果是spam

    为了能够控制在不同场景下面的转换,使用了if name == ‘main‘:,当做脚本执行的时候,逻辑写到if name == ‘main‘:下面。

    当做模块导入的时候,不会执行if name == ‘main‘:下面的内容。

    4 模块搜索路径

    总结模块查找的顺序:

    内存—>内建—>sys.path
    sys.path 的路径是以执行文件为基准的

    在不同的路径中的调用,在dir1中调用dir2中的内容

    import sys # 先导如sys模块
    
    sys.path.append(r"D:Python_fullstack_s4day35模块dir1") # 在sys.path的路径中添加dir1的路径    r是在win平台的转义
    
    import spam  # 添加路径后再调用spam 
    
    """
    结果:
    from dir1  # 这是spam中打印的内容
    """
    

    5 编译Python文件

    pyc文件是在导入模块的时候进行编译的,提高模块的导入速度,只有import/from import才能产生

    提前编译

    python -m compileall /module_directory 递归着编译
    

    6 包

    package是有init.py 文件的包

    包的本质就是一个包含init.py文件的目录。

    6.1

    创建一个包的目录结构,可以把包想象成一个大的模块

    glance/                   #Top-level package
    
    ├── __init__.py      #Initialize the glance package
    
    ├── api                  #Subpackage for api
    
    │   ├── __init__.py
    
    │   ├── policy.py
    
    │   └── versions.py
    
    ├── cmd                #Subpackage for cmd
    
    │   ├── __init__.py
    
    │   └── manage.py
    
    └── db                  #Subpackage for db
    
        ├── __init__.py
    
        └── models.py
    

    文件的内容:

    #文件内容
    
    #policy.py
    def get():
        print('from policy.py')
    
    #versions.py
    def create_resource(conf):
        print('from version.py: ',conf)
    
    #manage.py
    def main():
        print('from manage.py')
    
    #models.py
    def register_models(engine):
        print('from models.py: ',engine)
    

    想要在外部是用glance-api-policy中的文件

    import方法

    import glance.api.plicy   # 用点的方式
    
    glance.api.plicy.get() # 通过import导入的还是要用名字的方式进行使用
    '''
    结果:
    from policy.py   # policy中的get的内容
    '''
    

    from import方法

    from glance.api.plicy import get  # 下面使用的时候就直接使用了
    
    get()
    

    6.2 小结

    导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,

    对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

    需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

    6.3 init.py文件

    包都有init.py文件,这个文件是包初始化就会执行的文件,可以为空,也可以是初始化的代码

    导入包的时候,仅仅做的就是执行init.py

    from  glance.api import plicy   # 导入的是glance  api
    
    '''
    结果:
    glance 的包
    init 的包
    '''
    

    下面用import *来测试,也是一样的,但是api下面的内容找不到

    from glance.api import *   # 这里则是导入包,执行inti,*对应的是__all__中的
    '''
    结果:
    glance 的包
    init 的包
    '''
    
    from glance.api import *
    
    print(x)
    print(y)
    '''
    结果:
    glance 的包
    init 的包
    1
    2
    '''
    '''
    这是api中__init__,所以*是对应的__all__中的内容
    __all__ = ["x", "y"]
    x = 1
    y = 2
    
    '''
    

    7 绝对导入和相对导入

    7.1 绝对导入是从包的最开始的位置开始

    从test的sys.path的列表中寻找

    绝对导入的缺点是包的名字改变的话有问题

    在api的init.py下面写

    from glance.api import plicy
    from glance.api import versions
    

    test的使用

    import glance.api  # 仅仅是导入了glance.api  实际是找不到plicy的,因为导入模块仅仅是执行了__init__
    
    print(glance.api.plicy)
    
    '''
    结果:
    glance 的包
    init 的包
    <module 'glance.api.plicy' from 'D:\Python_fullstack_s4\day35\包\glance\api\plicy.py'>
    '''
    

    7.2 相对导入

    .—当前目录
    ..—上一级的目录

    from . import plicy,versions  #  通过当前目录的方式导入,当前的目录是api
    

    注意这种方式的init自己执行的时候会报错

    导入包的执行效果

    import glance.api
    
    print(glance.api.plicy.get())
    print(glance.api.versions.create_resource('aaa'))
    '''
    结果:
    from . import plicy,versionsglance 的包
    init 的包
    from policy.py
    None
    from version.py:  aaa
    None
    '''
    

    8 通过包调用内部的所有的

    这是glance的包中的init

    from .api.plicy import get   # 都是用的相对导入
    from .api.versions import create_resource
    from .cmd.manage import main
    from .db.modules import register_models
    

    包的定义者容易管理,对于使用者来说,使用的不知道是包还是模块

    test文件调用的方式

    import glance
    
    glance.get()  # 直接就能够使用
    '''
    glance 的包
    init 的包
    cmd 的包
    from policy.py
    '''
    

    8 包遵循的原则

    特别需要注意的是:可以用import导入内置或者第三方模块,但是要绝对避免使用import来导入自定义包的子模块,应该使用from… import …的绝对或者相对导入,且包的相对导入只能用from的形式。

    包是给别人用的,是不能自己运行的。自己运行的时候会出错

    9 在任意位置都能调用包

    关键是在运行的的文件查找到的是当前目录的sys.path,如果在别的目录中使用的话就需要找到包的父目录

    首先找到文件的绝对路径

    import sys
    import os
    
    p=os.path.abspath(__file__)  # 打印的是文件的绝对路径
    print(p)
    
    '''
    结果:
    D:Python_fullstack_s4day35包	est.py
    '''
    
    p = os.path.dirname(os.path.abspath(__file__)) # 返回的是文件的上一级目录
    print(p)
    
    '''
    结果:
    D:Python_fullstack_s4day35包
    '''
    

    下面的目录结构是

    D:.day35
    ├─包
    │  └─glance
    │      ├─api
    │      │  └─__pycache__
    │      ├─cmd
    │      │  └─__pycache__
    │      ├─db
    │      │  └─__pycache__
    │      └─__pycache__
    ├─模块
    │  ├─dir1
    │  │  └─__pycache__
    │  ├─dir2
    │  └─__pycache__
    └─练习
    
    import sys
    import os
    
    base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    # sys.path.append(r"%s"%(base_path)) # 把父目录添加到sys.path中
    sys.path.append(r'%s包' %(base_path))  # 拼接路径,这里拼接的是有glance的包
    print(base_path)
    
    import glance
    glance.get()
    '''
    结果:
    D:Python_fullstack_s4day35
    glance 的包
    init 的包
    cmd 的包
    '''
    
  • 相关阅读:
    [2019.2.24]BZOJ4591 [Shoi2015]超能粒子炮·改
    [2019.2.13]BZOJ4318 OSU!
    [2019.1.17]BZOJ1066 [SCOI2007]蜥蜴
    [2019.1.15]BZOJ2152 聪聪可可
    [2019.1.17]BZOJ3993 [SDOI2015]星际战争
    [2019.1.14]BZOJ2005 [Noi2010]能量采集
    [2019.1.10]BZOJ1853 [Scoi2010]幸运数字
    [2019.1.9]BZOJ2299 [HAOI2011]向量
    yyb博客的几道神仙题
    CQOI2018异或序列 [莫队]
  • 原文地址:https://www.cnblogs.com/Python666/p/6802219.html
Copyright © 2020-2023  润新知