通过如下代码初始化一些包、文件,用来做测试
import os
os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/models.py','w'))
map(lambda f:f.close() ,l)
.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同级别的文件中测试
import glance.db.models
glance.db.models.register_models('mysql')
from glance.db import models
models.register_models('mysql')
输出如下:
E:\python\python_sdk\python.exe E:/python/py_pro/python.py
from models.py: mysql
from models.py: mysql
Process finished with exit code 0
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的init.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
我们在glance\api下创建init.py文件
import glance.api
import glance.api.policy
输出如下:(如果单独为上面每一行代码做测试,都会输出如下,输出一次是因为第一次导入已经加载进内存)
api init
在讲模块时,我们已经讨论过了从一个模块内导入所有,此处我们研究从一个包导入所有。
此处是想从包api中导入所有,实际上该语句只会导入包api下init.py文件中定义的名字,我们可以在这个文件中定义all_:
我们修改glance\api包下的init文件
此时我们在于glance同级的文件中执行
from glance.api import *
print(x)
func()
policy.get()
#如下错误NameError: name 'versions' is not defined
# versions.create_resource(1)
输出如下:
E:\python\python_sdk\python.exe E:/python/py_pro/python.py
api init
10
from api.__init.py
from policy.py
Process finished with exit code 0
特别需要注意的是:可以用import导入内置或者第三方模块(已经在sys.path中),但是要绝对避免使用import来导入自定义包的子模块(没有在sys.path中),应该使用from… import …的绝对或者相对导入,且包的相对导入只能用from的形式。
比如我们想在glance/api/versions.py中导入glance/api/policy.py
import sys
print(sys.path)
import policy
policy.get()
输出如下:
E:\python\python_sdk\python.exe E:/python/py_pro/glance/api/versions.py
['E:\\python\\py_pro\\glance\\api', 'E:\\python\\py_pro', 'E:\\python\\python_sdk\\python36.zip', 'E:\\python\\python_sdk\\DLLs', 'E:\\python\\python_sdk\\lib', 'E:\\python\\python_sdk', 'E:\\python\\python_sdk\\lib\\site-packages']
from policy.py
没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到
我们接下来看一个失败的例子,比如我们在于glance同级下的一个python.py文件中导入version.py,如下
python.py
from glance.api import versions
versions.py如下
import policy
policy.get()
报错如下:
Traceback (most recent call last):
File "E:/python/py_pro/python.py", line 18, in <module>
from glance.api import versions
File "E:\python\py_pro\glance\api\versions.py", line 10, in <module>
import policy
ModuleNotFoundError: No module named 'policy'
由于上述弊端,我们就利用绝对方式导入模块
所有的模块导入都从“根节点”开始
根节点的位置由sys.path中的路径决定
项目的根目录在sys.path中存在是因为pycharm的作用
如果希望程序能处处执行,需要手动修改sys.path
python.py
import sys,os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
print(BASE_DIR)
sys.path.append(BASE_DIR)
from glance.api import versions
versions.py
from glance.api import policy
policy.get()
这样在执行python.py就不会报错了,会输出如下的信息:
E:\python\python_sdk\python.exe E:/python/py_pro/python.py
E:\python\py_pro
from policy.py
Process finished with exit code 0
只关心相对自己当前目录的模块位置就好
不能在包的内部直接执行
不管根节点在哪儿,包内的模块相对位置都是正确的
比如在glance\api包下的versions.py引入同包下的policy.py模块是报错的如下:
versions.py
from . import policy
policy.get()
在version.py界面执行,输出如下错误信息:
E:\python\python_sdk\python.exe E:/python/py_pro/glance/api/versions.py
Traceback (most recent call last):
File "E:/python/py_pro/glance/api/versions.py", line 4, in <module>
from . import policy
ImportError: cannot import name 'policy'
Process finished with exit code 1
因为不能在包的内部直接执行
我们在glance包同级目录下python.py测试下看看效果怎样?
python.py
from glance.api import versions
输出如下:
from policy.py
单独导入包名称时不会导入包中所有包含的所有子模块,如
在与glance同级的python.py中
import glance
glance.cmd.manage.main()
报错如下:
E:\python\python_sdk\python.exe E:/python/py_pro/python.py
Traceback (most recent call last):
File "E:/python/py_pro/python.py", line 9, in <module>
glance.cmd.manage.main()
AttributeError: module 'glance.cmd' has no attribute 'manage'
在glance/init.py中
from . import cmd
在glance/cmd/init.py中
from . import manage
然后执行python.py输出如下,引入成功!!
from manage.py