写在之前:
我就根据我自己的理解来解决这个概念
模块:
一个.py文件,就一个模块,在这个.py文件里面可以写函数、类、方法等
包:
把几个模块放在一个目录下面,再加上一个__init__.py文件,就构成了一个包
这两个概念很简单,重点在于 我使用import时遇到的两个问题。
先建一个包结构,如下
test_parent/
__init__.py
one.py
run.py
test_child/
__init__.py
two.py
three.py
one.py/
# 空
run.py/
from test_child import three
two.py/
# 空
three.py/
import one
from test_child import two
问题1:
: cd 到test_child 目录后,在cmd中执行 "python three.py",然后报错说:找不到模块one。
我之前在pycharm中写项目,都是这样建包结构的,也没有发现遇到,怎么在cmd下运行就出问题了?
后来才明白原因是这样:
*在pycharm中运行three.py时,会自动把根包目录,加入到path(环境变量)中
*在cmd中,python xxx.py 执行脚本时,只会把该脚本所在目录(即:test_child)加入到path中,并没有把根包目录test_parent加入到path中
*所以,当执行到 import xxx 时,是先从test_child目录下开始查找模块的,没有找到,就会报错了
解决方案:
在根包目录下,建一个入口模块,即run.py,然后在这里去调用其他模块的方法
然而,当使用相对导入时,在这里又会遇到另一个问题,如下。
问题二:
假如,在three.py中,把 import one 改成了 from .. import one,当我在cmd执行:python run.py时,会报错说:
当执行到three.py / from test_child import two这行时,发现test_child已经是根包目录了。
这时大家可能会说,不对呀!明明是test_parent才是根包目录呀?!
原因:
当你使用相对导入时,你要知道这样一个知识点:
python 不会把你入口所在的那个目录,当成一个包
你执行的命令是:python run.py,所在目录是:test_parent
test_parent 就不再是一个包了
至于为什么这样搞?那我就不知道了,有时间的人可以看看官方文档研究下,知道结果了告诉我下 ^O^
解决方案:
1、不使用相对导入,即:
把 from .. import one 写成 import one,然后就不会报错了
2、在test_parent外面,再建一个目录,把run.py放在这个目录下,这时目录结构是:
test_grandparent/
run.py
test_parent/
__init__.py
one.py
run.py
test_child/
__init__.py
two.py
three.py
这时执行python run.py,也不会报错(别忘了cd 到相应的目录下)
一般来说:
入口都是放在项目的根目录下,项目的根目录下,通常也不会有__init__.py
网友评论