本文主要是总结我这两天对于python中的引用以及相应报错信息的总结
从而可以指导对自己建包,以及如何使用包,处理引用问题。
py可以引用同目录下包的所有模块
- 这是既定事实,所以当你调用一个第三方的包时,就可以将py和包放在同一目录下
- 当然这其中可能会出现pycharm引用标红的问题,那是pycharm的问题,对于python来说不影响(详情可见 运行没有问题,pycharm却标红引用?)
- 同时,因为pycharm会因为工作区的问题,将正确的引用标红,那么反推,如果pycharm没有标红,也不代表没有引用问题存在
当py并不与第三方包在同一目录下时
- 如果我们pip install了一些包,那么就直接import
- 而对于我们拷贝,下载过来的,没有安装的包,就需要麻烦一点了
- 简单却麻烦的方式
- 在py中将 所需引用的包的 父 路径加入python的系统路径(仅临时生效)
- python运行时需要import时,就会去自己的系统路径中进行搜索 (sys.path,具体就不解释,自行百度,不过提示一句,若import多个模块,则sys.path.append一定要放到第一个,不然不生效)
- eg.
- 这里我们要引入try路径下的ansemb包,那么就将它的父节点路径导入(忽略标红,这是正常的)
- 其实这里的操作就是等价于我们在pycharm中,右键文件夹,make directory as source root
- 简单也不怎么方便的方式
- 在你的 /python安装目录/site-package/下创建xxx.pth(记不太清了,自己查一下),将要引入的包的父路径放入,这样相当于永久添加路径
- 麻烦在于,如果这个引入的第三方包是临时的,以后还得改,容易忘了改
有没有__init__.py其实影响不大
- 不是很确定,不过好像是这样
- 实测有没有它 都可以正常的引入
- 看了别的博客说,python3.3之后,directory都是默认的隐式包,所以不是很需要__init__.py来标识包,它的目的还是更多的在于控制
当前py要运行 用绝对路径,当前py被引用 用相对路径
- 特别是我们要建一个包的时候,很头疼,里面的import,from . import,很容易报错 no module,于是记住本节的标题,就可以轻松规避这些问题
- 用下面的例子来做演示
eg
目标:
- 包外的demo引用包中的test模块
- 包内的test引用同级目录下test2,分别采用绝对路径和相对路径的方式引用
- 分别运行demo和test,观察 在绝对路径和相对路径下是否能够正常运行,如果报错,报的什么错
(文件的取名是我在解决问题时看到别人博客,顺手借鉴的取名,最近写代码,取模块名、变量名已经累了,不想再取名了)
文件结构如下面(为了方便看,我把init都去掉了)
|--demo.py
|--try
|--ansemb
|--dataset
|--test.py
|--test2.py
# test2
def ok():
print("test2")
#demo
#引入了ansemb的路径,可以放在任意位置运行
import sys
sys.path.append(r"C:\Users\pan\PycharmProjects\pythonProject\try")
from ansemb import config
from ansemb.dataset import test
# config.ok()
test.ok2()
- 我们主要看test、test2、和在包外的demo.py
- 在demo中,引入ansemb.dataset.test,调用其ok2()方法
- test中需要引入同级目录下的test2
test使用 相对路径 引入test2
- 运行demo,正常打印
- 运行test
test使用 绝对路径 引入test2
- 运行demo
- 运行test
于是可以得到总结,同一包里进行引用时,如果需要运行自己,则使用绝对路径;如果是其他py引用自己,那么使用相对路径
原因猜想
其中的原因我结合看的博客,简单分析一下,不确保准确,如有大佬,可以评论区讲一下正确理解
使用相对路径
- 当直接运行test时,python默认test为主模块,其name为"main",所以就会把相对路径中的 . . . 换成"main",变成"from main import test2",这自然就无法找到test2了;而使用demo引用test时,demo的name是"main",test还是正常的,所以可以正常使用相对路径
使用绝对路径
- 直接运行test,就会以自己为根目录,此时就可以直接import当前目录下的test2,这没问题;而如果使用demo引入test运行,对于demo来说,需要引入test的引入test2(有点绕),那么此时以demo为准,为工作区,它的目录下没有test2,其他sys.path也都找不到,所以报错no module named test2
- 那么设想一下,如果我们在demo路径下新建一个空的test2,是不是就能找到test2了?是的,那么此时,因为空,所以会报错test2 has no attribute ok这个信息,我们来试一下
参考
https://blog.csdn.net/qq_34687559/article/details/122474888
https://zhuanlan.zhihu.com/p/349407590
https://blog.csdn.net/weixin_39738273/article/details/111635095