python 多层结构目录之间包的引用问题


写了这么久的python,发现连最基本的问题还没有搞懂。在写比较大的项目点时候,可能会涉及到不同包下模块的引用,经常会出现无法引用自己写的模块的问题。
核心就是两个概念:模块和包。
模块:实现一个功能,本质是*.py文件
:定义了一个由模块和子包组成的Python应用程序执行环境,本质就是一个有层次的文件目录结构(必须带有一个__init__.py文件)。

在较大型的项目中,我们的代码不可能写在一个脚本中,需要根据功能拆分成不同部分,对于重复使用的功能就会涉及到模块之间的调用,这时就会出现各种包、模块引用不成功的bug,下面以具体例子记录下我的理解。

一、pycharm和cmd中的使用

1.1、项目结构目录

在这里插入图片描述

  • 最外层文件夹名称test_package,包含文件夹package1、package2,文件test_all.py。
  • package1下有文件__init.py、test1_1.py、test_pak1.py
    test1_1.py:加法运算
def plus(a,b):
	return a+b

test_pak1.py :调用test1_1.py中的加法运算

from test1_1 import plus

if __name__ == '__main__':
    a=4
    b=5
    c=plus(a,b)
    print(c)

package2下有__init__.py、test2_1.py、test_pak2.py
test2_1.py:减法运算

def minus(a,b):
   return a-b

test_pak2.py:分别调用test2_1.py下的减法运算和package1下的test1_1.py中的加法运算

from package2.test2_1 import minus
from package1.test1_1 import plus

if __name__ == '__main__':
    a=4
    b=2
    print(minus(a,b))
    print(plus(a,b))

1.2、同级目录下的调用

test_pak1.py调用同级目录下test1_1.py中的plus()函数。
运行test_pak1.py
在这里插入图片描述
在cmd中运行结果一样。

1.3、不同级的调用

package2下的test_pak2.py调用package1下的test1_1.py中的plus()函数。
运行test_pak2.py
在这里插入图片描述
在cmd中运行会报错,提示找不到package2,出错原因我们稍后解释。
在这里插入图片描述

1.4、父级目录调用子级目录下的模块

运行test_all.py
在这里插入图片描述
在cmd中可以也正常运行。

二、出错原因和解决方法

2.1 出错原因

1.3节中不同包中的模块相互调用为啥在pycharm中可以执行,在cmd中就提示找不到package2了呢,这里要简单解释一下import的机制(具体原理会单独写篇文章介绍)。总的来说要想正确import模块,模块必须在sys.path中能被找到。
可以简单的认为 import 的查找顺序是:
1、内置模块
2、.py 文件所在目录
3、环境变量 PYTHONPATH中列出的目录(类似环境变量 PATH,由用户定义,默认为空);
4、pip 或 easy_install 安装的包

我们在test_pak2.py中打印出sys.path。

import sys

for i in sys.path:
    print(i)
from package2.test2_1 import minus
from package1.test1_1 import plus

if __name__ == '__main__':
    a=4
    b=2
    print(minus(a,b))
    print(plus(a,b))

在pycharm中运行
在这里插入图片描述
可以看到不光是test_pak2.py所在的文件夹package2被加载,文件夹package2的父级文件夹test_package,再上一级文件夹Python也都被加载进来了,因此包package1、package2可以被sys.path找到,并成功加载。

from package2.test2_1 import minus
from package1.test1_1 import plus

在cmd中测试
在这里插入图片描述
可以看到在cmd中执行test_pak2.py时,sys.path只是把test_pak2.py所在的路径D:\project\Python\test_package\package2加入进来了,在这个路径下找package1、package2当然就找不到了。

那么为啥pycharm可以将项目所在路径全部加载进sys.path而cmd只能加载py脚本所在路径?
原因是我在pycharm中把test_package设置为source root了。
在这里插入图片描述
在pycharm中对一个目录不设置Sources Root时,就是一个带点的文件夹。
在这里插入图片描述
设置Sources Root时是不带点的蓝色文件夹,因此很容易区分。
在这里插入图片描述
现在我们把test_package的Sources Root去掉,重新在pycharm里执行test_pak2.py在这里插入图片描述
可以看到这时错误就和cmd中一样了。

2.2 解决办法

如果就是想在cmd中使用不同包之间的模块调用方式,问题该怎么解决呢?
第一种方法:sys.path.append()

import sys
sys.path.append("..")
for i in sys.path:
     print(i)

from package2.test2_1 import minus
from package1.test1_1 import plus

if __name__ == '__main__':

    a=4
    b=2
    print(minus(a,b))
    print(plus(a,b))

结果
在这里插入图片描述
“..” 表示当前目录的上一级目录,这句话的意思是将test_pack2.py的上一级目录加载进sys.path中。当然也可以用绝地路径。sys.path.append(r"D:\project\Python\test_package")
结果
在这里插入图片描述
第二中方法:设置环境变量PYTHONPATH(记得重启)
在这里插入图片描述
第一个应该是安装qgis的时候自动添加的,这也是为啥之前输出sys.path的时候会有qgis的路径。
直接运行python test_pak2.py
在这里插入图片描述

第三种方法:使用-m方式运行,需要在test_pak2.py的上一级目录执行
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GHZhao_GIS_RS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值