最近在自己自定义的包中相互引用文件时遇到不少问题,以前对包的了解不深,只是停留在会简单调用,但是自己构建的时候才发现问题没那么简单,于是便记录梳理一下
在查阅资料之前,明确了有以下几个问题:
- 包与模块的区别
- 自定义的包,之间如何导入
包与模块
我的理解:
包(Package):包含__init__.py的文件夹都可以视为包
模块(Module):以.py结尾的文件都可以视为模块
from package import *
F:\> tree
mypackage
- A
- __init__.py(空)
- B
- __init__.py(空)
- __init__.py(空)
新建项目结构如上
# 在F:\目录启动命令行,执行ipython
[In1]: from mypackage import *
[In2]: dir()
[Out2]: [
...
]
当__init__.py文件为空时, 以”*”导入mypackage下的模块,A、B是不会被导入的
# mypackage/__init__.py
# 添加一下代码
__all__=["A","B"]
保存后重启命令行,再次执行导入
[In1]: from mypackage import *
[In2]: dir()
[Out2]: [
...
"A",
"B",
...
]
此时使用“*”这种导入方式,会将__init__.py中__all___的内容导入,也就是说要想将mypackage包下的子包或模块导入,需要在__all__变量中添加
from ./.. import module/class/variable
mypackage
│ banana.py
│ __init__.py
│
├───A
│ │ apple.py
│ │ __init__.py
│
├───B
│ mango.py
│ orange.py
│ __init__.py
# A\apple.py
class Apple():
description = "I'm apple!"
# B\mango.py
class Mango():
description = "I'm a mongo!"
# B\orange.py
from ..A.apple import Apple
from . import mango
fruit1 = Apple()
fruit2 = mango.Mango()
print(fruit1.description)
print(fruit2.description)
自定义包内相互调用方式
同级目录下调用
导入方式
from . import module
from .module import class
from .module import variable
跨目录调用
导入方式
from .. import package
from ..module import class/variable
from ..package import module
from ..package.module import class/variable
from . 相当于在此文件的目录下查找
from .. 相当于在此目录的上一级去查找
F:\> ipython
[In1]: from mypackage.B.orange import fruit1, fruit2
[In2]: fruit1.description
[Out2]:
"I'm apple!"
[In3]: fruit2.description
[Out3]:
"I'm mango!"
注意:此种调用方式只能在包中使用,且只有在不主动使用时才有效,不然会报错,原因是:“.”,“..”这种方式是使用相对路径去寻找的,只有当在包外面调用时才成立,如果直接运行(比如:orange.py)带有“.”, “..”的.py文件,此时运行空间是相对文件自身的,所以相对路径是不成立的。也就是说带有’.’的.py文件需要在相对此文件目录的上一级(mypackage)才能使用,当前目录(B)是运行不了的,同理,“..”,需要在相对此文件目录的上两级的(mypackage外)才能使用
简单来讲:“.”是在文件目录下的,相对路径的表达方式才生效,文件本身是没有“.”