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

问题描述 投票:0回答:5

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

我的目录结构是这样的:

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

当我使用

a.py
b.py
导入
from subpackage1 import a
时,我收到 ModuleNotFoundError。我似乎无法从父目录导入文件。

一些解决方案建议在每个目录中添加一个空文件

__init__.py
,但这不起作用。作为解决方法,我将以下内容放入每个子文件(即
a.py
b.py
)中以访问父目录:

import os
import sys
sys.path.append(os.path.abspath('..'))  

我尝试在子文件中输出

sys.path
,它只包含当前文件路径和anaconda路径,所以我必须将
..
附加到
sys.path

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

python-3.x python-import
5个回答
5
投票

假设我们有这些文件和目录树:

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

2 directories, 5 files

因此,这里是如何从

a.py
inti
b.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

当我们处于 /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

2
投票

您遇到的第一个问题是由于

from subpackage1 import a
模块中的
b.py
行造成的。

b.py
位于您的
subpackage2
包中,它是
subpackage1
的兄弟包。因此,尝试运行
from subpackage1 import a
意味着
subpackage1
subpackage2
之内,这是不正确的。另请注意,在 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
投票

首先,你需要在subpackage1中创建文件

__init__.py
来声明它是一个模块

touch subpackage1/__init__.py

其次,你可以尝试在python3中进行相对导入

# b.py
from ..subpackage1 import a

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

$PYTHONPATH

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

0
投票

访问子包的一种方法是使用

.
运算符一直到顶部包或文件目录。因此,如果结构是

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

然后你使用以下

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

statements...

from
语句必须一直到达顶层目录,涵盖
a.py
b.py


0
投票

这个 SO Q&A 讨论了将项目根目录添加到 PYTHONPATH 的选项。

1。 mac/linux:

export PYTHONPATH="${PYTHONPATH}:/path/to/Project_top_directory"
添加到您的
~/.bashrc

2。 路径配置文件:
或者,您可以创建一个 path 配置文件

# find directory
SITEDIR=$(python -m site --user-site)

# create if it doesn't exist
mkdir -p "$SITEDIR"

# create new .pth file with our path
echo "$HOME/foo/bar" > "$SITEDIR/somelib.pth"
© www.soinside.com 2019 - 2024. All rights reserved.