• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于python:终于搞懂了Python模块之间的相互引用问题

python 搞代码 4年前 (2022-02-20) 27次浏览 已收录 0个评论

摘要:具体解说了相对路径和绝对路径的援用办法。

在某次运行过程中呈现了如下两个报错:

报错1: ModuleNotFoundError: No module named '__main__.src_test1'; '__main__' is not a package
报错2: ImportError: attempted relative import with no known parent package 

于是基于这两个报错探索了一下python3中的模块互相援用的问题,上面来一一解析,请急躁看完。

好的,咱们先来结构第一个错:

测试代码构造如下:

|--- test_main.py
|--- src
  |--- __init__.py                                                              
    |--- src_test1.py
    |--- src_test2.py

src_test2.py 代码

class Test2(object):
    def foo(self):
        print('I am foo')

src_test1.py 代码,援用Test2模块

from .src_test2 import Test2

def fun1():
    t2 = Test2()
    t2.foo()
if __name__ == "__main__":
    fun1()

此时运行 src_test1.py 报错“No module named ‘__main__.src_test1’; ‘__main__’ is not a package”

问题起因:

次要在于援用src_test2模块的时候,用的是相对路径”.”,在import语法中翻译成”./”,也就是当前目录下,按这样了解也没有问题,那为什么报错呢?

从 PEP 328 中,咱们找到了对于 the relative imports(绝对援用)的介绍

艰深一点意思就是,你程序入口运行的那个模块,就默认为主模块,他的name就是‘main’,而后会将本模块import中的点(.)替换成‘__main__’,那么 .src_test2就变成了 __main__.src_test2,所以当然找不到这个模块了。

解决办法:

因而,倡议的做法是在 src同层级目录创立 援用模块 test_main.py(为什么不在src目录下创立,待会下一个报错再讲),并援用src_test1模块,代码如下:

from src.src_test1 import fun1

if __name__ == "__main__":
    fun1()

test_src 代码:

from src_test1 import fun1

if __name__ == "__main__":
    fun1()

执行报错:ImportError: attempted relative import with no known parent package

问题起因:

当执行test_src时,按上文了解,此时执行文件所在的目录为根目录,那么援用test1的时候,须要留神的是,此时test1的name属性不再是src.src_test1,因为程序感知不到src的存在,此时他的绝对路径是 src_test1,此时再次援用相对路径查找的test2,同样的步骤,须要先找到父节点,而此时他本人就是根节点了,曾经没有父节点了,因而报错“no known parent package”。

解决办法:

此时为了防止父节点产生矛盾,因而将test1中的引入去掉绝对援用即可

from .src_test2 import Test2    -->    from src_test2 import Test2

持续深刻:

那应用相对路径和绝对路径,编译器是怎么找到这个模块的呢?

执行import的时候,存在一个引入的程序,即优先查找执行目录下有没有此文件,如没有,再查找lib库下,如还没有,再查找sys.path中的门路,如再没有,报错。

所以不论是当前目录,还是 sys.path中的目录,都能够查到 src_test2这个模块,就能够编译胜利。

号外

解决完上述问题后,不论咱们用哪种形式,咱们调试代码时,都是单个文件调试,但此时根目录就不对了,import形式又要改变,执行起来很麻烦,所以这里举荐另一种形式(有更好的形式欢送留言),应用sys.path.append()的办法

import sys,os
sys.path.append(os.getcwd())
from src.src_test2 import Test2

应用append的形式,将程序文件根目录放进了sys.path中,而后再援用相对门路,这样的形式,不论应用上文中的第一或第二执行形式都能够调用,也能够独自编译test1文件,不必批改import门路,也是绝对平安的形式。然而毛病就是,如果你批改了某一个包名,须要将所有援用中央都批改一下,工作量大,所以就地取材。

综上,具体解说了相对路径和绝对路径的援用办法,当初你应该对import导入的问题有了清晰的了解吧

备注:本文基于Python3.7版本测试

点击关注,第一工夫理解华为云陈腐技术~


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于python:终于搞懂了Python模块之间的相互引用问题

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址