python | 关于不同层级的包package之间进行import的问题

一 写在前面

未经允许,不得转载,谢谢~~~

2020的第一篇博客就献给踩过的第一个坑吧 (〃´-ω・)

大家新年快乐!新的一年冲鸭~~~

二 最简单的import情况

日常情况下我们自己写程序一般就会碰到以下两种情况的代码调用:

1. 同级目录

这是最简单的一种情况。

例如同级目录下的main.py要调用model.py,那么直接import即可。

Projects/
    - main.py
    - model.py

2. 子级目录

这也是很常见的一种情况。

例如根目录下的main.py要调用models子集目录下的p3d.py

  • 首先在models文件夹下新建一个__init__.py文件,空即可。
  • 然后在main.py中即可import models.p3d, from models.p3d import xx
Projects/
    - main.py
    - models/
        - p3d.py
        - c3d.py
        - i3d.py

三 比较复杂的package调用情况

3.1 场景描述:

以上的两种情况基本都是所有的代码都是自己写的这种情况,但我们有的时候需要从github上扒一份别人的代码作整个项目里面的一个component,这种时候就没有那么方便。

通常下载的代码本身就有很多相互代码之间的相互调用关系,所以不能轻易改变其路径,不然你可能需要挨个修改每个的调用。

当然最简单的方法是将你自己的东西全部放在他的目录结构里面去,例如在这个例子中将main.py挪到detectron 中,将detectron作为你的项目主目录,但是这样子会破坏代码的结构性,不是很推荐。

例如detectron是原本独立的一份项目代码,我现在想将其加到我的Projects里面:
(具体目录结构如下示意)

Projects/
    - main.py
    - detectron/
        - demo/
              - demo.py
              - predict.py
        - detectron/
              - backbones/
                    - xxx.py
                    - ...
              - detection/
                    - xxx.py
                    - ...
        - __init__.py

3.2 解决思路:

  1. 那么第一件是在detectron中加入__init__,标注其为package
  2. 这个时候理论上来说我可以main.py中用import detectron.demo.predict的形式来调用predict中的内容。
  3. 但以上的情况仅限于predict.py里面没有调用其他detectron中的代码文件的情况,这一点对于一个集成性比较好的package是不可能的。会出错的原因在于在predict.py中调用其他的代码文件的时候是从它自己原来的主目录开始的,例如在它里面可能会通过import detectron.backbones.xxx的形式来调用backbones下的代码。
  4. 但是我们在main.py中去执行代码的时候,上面的方式就会出错,完整的应该是import detectron.detectron.backbones.xxx
  5. 所以解决方法有两个:
    • 1: 将所有原来代码中的import语句前面补上一个路径,即从:import detectron.backbones.xxx-->import detectron.detectron.backbones.xxx (推荐代码量小的情况使用)
      1. 解决路径检索不到的问题:
     import sys
     # add the path of detectron to your Projects
     sys.path.append('./detectron')
    

3.3 彩蛋:BUG

没想到还有吧哈哈哈哈哈!

正常情况下用sys将路径append进来以后就没有什么关系了,但是文章开头就是为了记录坑,在这个意义上前面的内容全是铺垫。/捂脸

这个BUG昨天找了将近2个小时─━ _ ─━✧

细心的同学可能注意到detectron有两个重名目录,一个是原本的主目录detectron/,一个是原来主目录下的子目录detectron/detecron/。这种情况如果将其作为独立的代码来看是完全没有问题的。但是在将原来的主目录放在Projects/下面的时候就出现问题了==

具体的表现在于我用sys.path.append的方式将detectron/加到路径里,正常情况下就可以不修改原来的import detectron.backbones.xxx的调用方式找到backbones里面的文件。

但是!!由于两个目录重名,所以在搜索的时候每次搜到上面那个detectron就停掉了,不会检索到下面的detectron

解决方法:

修改重名目录中的其中一个目录名。

四 写在最后

暂时就先写到这里吧

其实中间还尝试过想直接用过用subprocess.call来调用python xxx.py的方式来避免上面的问题,但是这样的问题是只能执行该文件,输出的结果只会打印在屏幕,么有办法直接将想要的结果return回来。

希望新的一年有时间多写一些blog(立个FLAG哈哈哈)

你可能感兴趣的:(python | 关于不同层级的包package之间进行import的问题)