导入包与模块
Posted cherry2020
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了导入包与模块相关的知识,希望对你有一定的参考价值。
import os os.makedirs(‘glance/api‘) os.makedirs(‘glance/cmd‘) os.makedirs(‘glance/db‘) ls = [] ls.append(open(‘glance/__init__.py‘,‘w‘)) ls.append(open(‘glance/api/__init__.py‘,‘w‘)) ls.append(open(‘glance/api/policy.py‘,‘w‘)) ls.append(open(‘glance/api/versions.py‘,‘w‘)) ls.append(open(‘glance/cmd/__init__.py‘,‘w‘)) ls.append(open(‘glance/cmd/manage.py‘,‘w‘)) ls.append(open(‘glance/db/__init__.py‘,‘w‘)) ls.append(open(‘glance/db/models.py‘,‘w‘)) map(lambda f: f.close() , ls)
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) money = 1000 def read1(): print(‘from the models->read1->money‘, money) def read2(): print(‘from the models->read2 calling read1‘) read1() def change(): global money money = 60
‘‘‘ 层级关系: test.py 模块名A 包名1/包名2/包名3/模块名B/变量名+函数名 ‘‘‘ # 在测试文件test.py中 # 可以写 import 包名1 # 可以写 import 模块名A # 可以写 from 包名1.包名2 import 包名3 # 可以写 from 包名1.包名2.包名3 import 模块名 # 可以写 from 包名1.包名2.包名3.模块名 import 函数名 或 变量名 ‘‘‘ # 错误写法 import 包名.包名.包名.模块名.函数名 或 变量名 # 错误写法 from 包名.包名 import 包名.模块名 ‘‘‘ ‘‘‘ 层级关系: test.py 包名0/包名1/包名2/包名3/模块名B/变量名+函数名 ‘‘‘ # 在测试文件test.py中 # 不可以写 from 包名1.包名2.包名3 import 模块名B # 不可以写 import 包名1 # python解读此语句后 先进行路径下的模块查找 即从test.py的[sys.path]路径中查找 包名1 # 和test.py所在目录同级的是包名0 因此会报错 ModuleNotFoundError: No module named ‘包名1‘ # 假设以test.py文件的执行 做为程序运行的入口,且当前各__init__.py文件的内容为空 # 此时test.py文件的工作目录路径被写入系统的[sys.path],且作为路径列表中的第一个元素 # 当然,如果你是用PyCharm,PyCharm还会自动补充当前路径的父一级目录 做为[sys.path]路径列表的第二个元素 # "导入工作"的内容1 —— 将被导入的对象 记录于 {sys.modules} 字典 # "导入工作"的内容2 —— 执行文件(包的__init__.py文件 或 模块名.py文件) # "导入工作"的内容3 —— 创建模块的名字空间 且将‘名字‘导入到执行入口所在的当前名字空间中 # 例1 import glance.db.models 导入的对象是三个 glance glance.db glance.db.models # 例2 from glance.db import models 导入的对象是三个 glance glance.db glance.db.models # 例3 from glance.db.models import register_models 导入的对象还是三个 glance glance.db glance.db.models # 例4 import glance 导入的对象只一个 glance # 以上例子 我们都显式可见地,仅通过写法就可知{sys.modules}字典中因Import导入新增了哪几个对象 # 你可以用print(sys.modules)去验证,仔细观察你会发现,每个新增对象都从其名字上描述了自己的所属 ‘‘‘ glance glance.db glance.db.models ‘‘‘ # 这种层级关系的另一处体现是,各包的__init__.py文件 和 模块名.py文件在被执行时,存在了调用先后顺序 # 这里补充一下,.py文件能被python执行的前提是 python能依据路径访问到此文件 # 而路径的成功访问基础是 sys.path + 向下的层级关系 ‘‘‘ test.py文件一直是我们执行的入口,在此文件中打印一下sys.path路径列表吧 python是以此路径为基础, 以包和包下模块的层级关系为辅助,访问查找被导入的包或模块的py文件并执行它们的 ‘‘‘ # 它们的执行被顺序体现如下 # 例 import glance ‘‘‘ 只执行 ======glance init 包的初始化======== ‘‘‘ # 例 import glance.db.models # 例 from glance.db import models # 例 from glance.db.models import register_models ‘‘‘ 都遵循下面的执行顺序 ======glance init 包的初始化======== ======db init 包的初始化======== ====models.py==模块文件被执行==== ‘‘‘ # 题外话 # 一旦{sys.modules}字典包与包、包与模块间的层级关系的明确 # PyCharm工具软件就可以协助我们在书写代码时,通过按键‘.‘ 关联显示出其备选项 # 例 import glance.db.models # glance.db.models.register_models(‘mysql‘) 可被通过按‘.‘键被快速写出,且可被执行 ‘‘‘ 思考问题 test.py文件中 只写import glance 让glance.db.models.register_models(‘mysql‘)在该文件中被成功执行 实践后,你会发现报错 AttributeError: module ‘glance‘ has no attribute ‘db‘ test.py文件中 将import glance 改为 import glance.db.models 再次实践 会发现 glance.db.models.register_models(‘mysql‘)被成功执行 借助两次实践过程中print(sys.modules)的对比结果 你会找到原因 ‘‘‘ # 解决办法 # 必须在{sys.modules} 字典中 在只有对象glance的基础上 再补充上如下两个对象 glance.db glance.db.models # 要写为{sys.modules} 字典新增对象 我们就必须令 # import glance.db 或 from glance import db # import glance.db.models 或 from glance.db import models # 这样的语句被执行, 而这样的语句我们又不想写在test.py文件中( 题目是 test.py文件中只写import glance 这一句) # 那么 我们可以借助包的初始化文件__init__.py的被执行 ‘‘‘ # 在glance包的__init__.py文件中 写如下代码 # from glance import db # 这句代码的执行 使得{sys.modules}字典可以新增 glance.db # 这句代码的执行 还使得 db包的初始化文件的也被执行 # 因此 我们在db包的__init__.py文件中 再次写如下代码 # from glance.db import models # 则{sys.modules}字典可以再次新增 glance.db.models # 且模块文件models.py文件会被执行 # 至此, ‘glance‘ ‘glance.db‘ ‘glance.db.models‘ 这三项都存在于{sys.modules}字典中 # test.py文件中虽只写了一句 import glance, # 但glance.db.models.register_models(‘mysql‘)已经可以被执行了 ‘‘‘ # import"导入工作"结束后的使用,其核心就是 只能使用当前名字空间中新导入的‘名字‘ # 你可以查看globals() # 你可以借助print(directory()) 对比查看执行入口test.py文件的当前名字空间中名字的变化 ‘‘‘ # 例1 import glance 当前名字空间中引入了 一个新名字glance 这是一个包名 # 例2 import glance.db.models 当前名字空间中引入了 一个新名字glance 这是一个包名 # 例3 from glance.db import models 当前名字空间中引入了 一个新名字models 这是一个模块名 # 例4 from glance.db.models import register_models 引入了 一个新名字 register_models 函数名 ‘‘‘ # 只要名字存在 该名字就可以被直接拿来使用 ‘‘‘ # 针对例1 直接用glance做代码书写的起始开头 如果 {sys.modules} 字典中 glance glance.db glance.db.models 都存在 # 则可以执行 glance.db.models.register_models(‘mysql‘) # 针对例2 直接用glance做代码书写的起始开头 glance.db.models.register_models(‘mysql‘) # 针对例3 直接用models做代码书写的起始开头 models.register_models(‘mysql‘) # 针对例3 直接用register_models做代码书写的起始开头 register_models(‘mysql‘) ‘‘‘ # 上述代码被执行时,函数register_models都是回到 模块models.py自身的名字空间内执行 # 即模块文件内的函数,都以文件的名称空间做为全局名称空间 # 模块models.py自身的名字空间 对内自称为__main__ 对外被称呼为__models__
以上是关于导入包与模块的主要内容,如果未能解决你的问题,请参考以下文章