python3.x:从父目录导入文件时出现ModuleNotFoundError

时间:2019-01-24 03:50:32

标签: python-3.x python-import

我是Python的新手。这真让我感到困惑!

我的目录结构是这样的:

Project
   | - subpackage1
           |- a.py
   | - subpackage2
           |- b.py
   | - c.py  

当我将a.py的{​​{1}}导入b.py时,会收到 ModuleNotFoundError 。看来我无法从父目录导入文件。

某些解决方案建议在每个目录中添加一个空文件from subpackage1 import a,但这不起作用。解决方法是,将以下内容放入每个子文件(即__init__.pya.py)中,以访问父目录:

b.py

我试图在子文件中输出import os import sys sys.path.append(os.path.abspath('..')) ,它仅包含当前文件路径和anaconda路径,因此我必须将sys.path附加到..

如何解决此问题?有没有更有效的方法?

4 个答案:

答案 0 :(得分:1)

您遇到的第一个问题是由于from subpackage1 import a模块中的b.py行。

b.py位于您的subpackage2软件包中,这是subpackage1的同级软件包。因此,尝试运行from subpackage1 import a意味着subpackage1subpackage2内,这是不正确的。另外请注意,在python3中,永远不要使用隐式相对导入,因为它不再支持它,而应使用显式相对导入。

在每个文件夹中添加__init__.py会将其转换为python软件包,您可以将其保留为空。您想用显式相对导入(如from subpackage1 import a或绝对导入(如from ..subpackage1 import a)替换from Project.subpackage1 import a。这将是编写程序包的有效而正确的方法,您可以通过编写导入Project并使用其子程序包和模块的脚本来对其进行测试。

但是,我假设您正在运行b.py作为测试导入的主要模块。这意味着您正在运行如下命令行:python b.py。像这样运行它,将为您提供一个模块搜索路径,该路径没有任何Project之类的父路径。即使您的软件包在技术上没有错,这也会导致您不断收到ModuleNotFoundErrors。这就是为什么您需要一种sys.path.append(...解决方法,该解决方法将您的父路径手动附加到模块搜索路径,以便将b.py模块作为主要模块运行。如果这可以帮助您测试代码,则请务必使用它,但是可以使用绝对和显式相对导入,因为包中的模块应该以这种方式工作。

答案 1 :(得分:0)

首先,您需要在subpackage1中创建文件__init__.py来声明它是一个模块

touch subpackage1/__init__.py

第二,您可以尝试在python3中进行相对导入

# b.py
from ..subpackage1 import a

或者您可以将当前目录添加到$PYTHONPATH

export PYTHONPATH=${PYTHONPATH}:${PWD}

答案 2 :(得分:0)

访问子包的一种方法是使用.运算符,一直到最顶层的包或文件目录。因此,如果结构是

top_directory
|- package1
   |- subpackage1
      |- a.py
|- package2
   |- subpackage2
      |- b.py

然后您使用以下内容

#b.py
from top_directory.package1.subpackage1 import a

statements...

from语句必须一直到达包含a.pyb.py的顶层目录。

答案 3 :(得分:0)

假设我们有以下文件和目录树:

$> tree
.
├── main.py
├── submodule1
│   ├── a.py
│   └── __init__.py
└── submodule2
    ├── b.py
    └── __init__.py

2 directories, 5 files

因此,这里有一个示例,说明如何从a.pyb.py进行导入,反之亦然。

a.py

try:
    # Works when we're at the top lovel and we call main.py
    from submodule1 import b
except ImportError:
    # If we're not in the top level
    # And we're trying to call the file directly
    import sys
    # add the submodules to $PATH
    # sys.path[0] is the current file's path
    sys.path.append(sys.path[0] + '/..')
    from submodule2 import b


def hello_from_a():
    print('hello from a')


if __name__ == '__main__':
    hello_from_a()
    b.hello_from_b()

b.py

try:
    from submodule1 import a
except ImportError:
    import sys
    sys.path.append(sys.path[0] + '/..')
    from submodule1 import a


def hello_from_b():
    print("hello from b")


if __name__ == '__main__':
    hello_from_b()
    a.hello_from_a()

然后, main.py

from submodule1 import a
from submodule2 import b


def main():
    print('hello from main')
    a.hello_from_a()
    b.hello_from_b()


if __name__ == '__main__':
    main()

演示:

当我们处于最高级别时,我们试图致电main.py

$> pwd
/home/user/modules
$> python3 main.py
hello from main
hello from a
hello from b

当w在/ modules / submodule1级别时,我们正在尝试调用a.py

$> pwd
/home/user/modules/submodule1
$> python3 a.py
hello from a
hello from b

在/ modules / submodule2级别上,我们试图调用b.py

$> pwd
/home/user/modules/submodule2
$> python3 b.py
hello from b
hello from a