导入模块
总结:
import
import 模块名
import 模块名 as 别名
import 模块名1,模块名2,模块名3...(不建议)
from ... import
from 模块名 import 模块文件里具体的功能名字
from 模块名 import 模块文件里具体的功能名字 as 别名
from 模块名 import * (不建议)
#以下两种仅仅针对*号做设置
1> 在模块文件里的功能名字前加_下划线 那么*里就不包含此功能 仅仅针对这里的*
2>在模块文件里设置 __all__['功能名1',“功能名2”...] 仅仅设置的包含在*号里,并不是所有
举例说明:
##重点: 源文件和现文件的名称空间
模块文件
spam.py
#spam.py print('from the spam.py') money=1000 def read1(): print('spam->read1->money',money) def read2(): print('spam->read2 calling read') read1() def change(): global money money=0
#import导入 import spam print(spam.money) print(spam.read1()) #调用的时候 需要加模块名作为前缀
#from ... import 导入 from spam import read1,read2,money print(read1()) print(money) #直接导入功能名字 可以直接调用
两种方法对比
import 需要添加前缀,但是不容易和当前文件中的变量混淆
from ... import 使用源文件的名字时无需添加前缀,方便 但是容易和当前文件中的名字混淆
查看当然导入的模块
import sys print(sys.modules)
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下
#test.py import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果. import spam import spam import spam ''' 执行结果: from the spam.py '''
导入模块做的事
1> 执行源文件
2>以一个源文件的全局名称空间
3>在当前位置拿到一个模块名,指向源文件的名称空间
把模块当做脚本执行
在模块文件的尾部加入以下代码,便于开发者调试,意思是把模块当做脚本执行的时候,才会执行以下代码
当做模块执行的时候 忽略
if __name__ == "__main__": import sys fib(int(sys.argv[1]))
模块的搜索路径
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。
所以总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
为了防止找不到模块,所以要把自定义的模块加入到sys.path路径中 方法如下
import sys print(sys.path) sys.path.append(r'F:\untitled\a\b\c') #或者 sys.path.insert(r'F:\untitled\a\b\c')
导入包
重要点:
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
重要: 一定要搞懂,谁是执行文件,执行文件的路径 就是sys.path第一个要找的路径。
导入方式
from 包名(如果有多级目录 包名.二级目录 .三级目录)import 文件名
理念:包也是一种模块,模块就是为了导入使用的 ,要给使用者提供方便
举个例子:
目录结构
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 #Subpackage for db
#文件内容 #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')
如上的目录结构和文件内容,如果想 实现包名.功能名 调用功能的话 那么 glance的 __init__.py 配置如下:
from glance.api.versions import create_resource from glance.cmd.manage import main from glance.api.policy import get
那么和glance同级目录的执行文件 就可以这样调用
import glance glance.get() glance.create_resource('test.conf') glance.main()
相对导入和绝对导入
依据上边的例子 继续说 (**执行文件和包是同级目录)
绝对导入的话 glance的 __init__.py 配置如下:
from glance.api.versions import create_resource from glance.cmd.manage import main from glance.api.policy import get
相对导入:
from .api.versions import create_resource from .cmd.manage import main from .api.policy import get #. 代表当前目录
现在有一个需求
api/policy.py 需要调用 cmd/manage.py里的功能,那么policy.py里需要增加的配置如下:
绝对导入
from glance.cmd.manage import main #新增内容 def get(): print('from policy.py') main() #新增内容 测试代用manage.py里的main功能
相对导入
from ..cmd.manage import main #新增内容 .当前目录 ..上一级目录 def get(): print('from policy.py') main() #新增内容 测试代用manage.py里的main功能
在执行文件里测试 如下
import glance glance.get() ''' 打印结果: from policy.py from manage.py #两个文件的内容都有了 '''
以上都是基于 执行文件和包在同一目录级别,如果不在同一目录级别 就需要将包的路径加入 sys.path
思路:
导入模块(包)
1> 执行文件如果不和模块(包)在同一目录,就加入到 sys.path里
2>如果是包 就在包的init文件里做好 包的导入
软件开发规范
常用模块
来源:https://www.cnblogs.com/lazyball/p/7269399.html