python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入

      • 导入同级包下模块
      • 包下的_init_py文件
      • 从同级包中导入所有
      • syspath导入模块错误原因
      • 绝对导入
      • 相对导入
      • 单独导入包

通过如下代码初始化一些包、文件,用来做测试

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)

文件结构关系如下:

python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入_第1张图片

导入同级包下模块

我们在与包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文件

不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的init.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
我们在glance\api下创建init.py文件
python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入_第2张图片

import glance.api
import glance.api.policy

输出如下:(如果单独为上面每一行代码做测试,都会输出如下,输出一次是因为第一次导入已经加载进内存)

api init

从同级包中导入所有

在讲模块时,我们已经讨论过了从一个模块内导入所有,此处我们研究从一个包导入所有

此处是想从包api中导入所有,实际上该语句只会导入包api下init.py文件中定义的名字,我们可以在这个文件中定义all_:
我们修改glance\api包下的init文件
python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入_第3张图片

此时我们在于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

sys.path导入模块错误原因

特别需要注意的是:可以用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'

解决方法:
python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入_第4张图片

在glance/init.py中

from . import cmd

在glance/cmd/init.py中

from . import manage

然后执行python.py输出如下,引入成功!!

from manage.py

你可能感兴趣的:(Python基础)