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 的包
'''
原文地址:https://www.cnblogs.com/Python666/p/6802219.html