Python + Submodules: ImportError: attempted relative import with no known parent package
Python + Submodules: ImportError: attempted relative import with no known parent package
我一直在为 python 上的相对导入而苦苦挣扎。
我的项目结构如下所示:
root_dir
├── main.py
├── Pipfile
├── Pipfile.lock
├── unit_tests
│ ├── __init__.py
│ ├── test_first.py
│ └── test_second.py
└── my_package
├── __init__.py
├── first.py
├── second.py
└── third.py
我想将位于 my_package
的文件中的一组函数导入 test_first.py
。
根据 official documentation 语法应如下所示:
from ..my_package import first
当我这样做时,出现以下异常:
Traceback (most recent call last):
File "/home/user/dev/root_dir/my_package/unit_tests/first.py", line 8, in <module>
from ..my_package import first
ImportError: attempted relative import with no known parent package
我还尝试使用以下语法导入文件:
from root_dir.my_package import first
当我这样做时,出现以下异常:
ModuleNotFoundError: No module named 'root_dir'
值得一提的是,我正在使用 pipenv
来处理虚拟环境。
知道为什么会这样吗?
谢谢。
我认为问题在于您的根目录不被视为 python 模块。
为了进行相对导入,您应该将“__init__.py”添加到您的根目录。
current working directory is not a package。用os.getcwd()
看看是什么,不过很有可能会是root_dir
.
这样的话,可以不用相对导入,直接按名称导入顶层包;你应该直接从 my_package
导入,像这样:
from my_package import first
...或者:
from my_package.first import do_something
复制的文件树:
root_dir
├── main.py
├── my_package
│ ├── __init__.py
│ └── first.py
└── unit_tests
├── __init__.py
└── test_first.py
main.py
的内容:
from unit_tests import test_first
if __name__ == "__main__":
test_first.test_something()
如果您尝试进行相对导入,即:from ..my_package import first
您将得到:
ImportError: attempted relative import beyond top-level package
首先,我将提供适合我的代码。然后,我会做一个简单的解释。这是一个简短的函数,可以让您从根目录导入。
解决方案
import os, sys
def access_root_dir(depth = 1):
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
args: list = [parent_dir]
for _ in range(depth):
args.append('..')
rel_path = os.path.join(*args)
sys.path.append(rel_path)
# At the top of test_first.py
access_root_dir(2)
import root_dir
由于根目录是 test_first.py
的祖父目录,您需要进入深度 2:
说明
我在我的一个项目中遇到了同样的问题并找到了
通过更改 sys.path
修复了从父目录导入的问题。使用类似的东西将绝对路径附加到根目录
sys.path.append(abs_path_to_root)
似乎不起作用,除非一切都是包的一部分。 Python 默认情况下不会访问导入中的父目录。
# Case 1: Relative path to parent - works
current_dir = os.path.dirname(os.path.realpath(__file__))
relative_path = os.path.join(current_dir, '..')
sys.path.append(relative_path)
import parent_module_name # This works for me (Python 3.9)
# Case 2: Absolute path to parent - Doesn't work
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
import parent_module_name # raises ModuleNotFoundError
我一直在为 python 上的相对导入而苦苦挣扎。
我的项目结构如下所示:
root_dir
├── main.py
├── Pipfile
├── Pipfile.lock
├── unit_tests
│ ├── __init__.py
│ ├── test_first.py
│ └── test_second.py
└── my_package
├── __init__.py
├── first.py
├── second.py
└── third.py
我想将位于 my_package
的文件中的一组函数导入 test_first.py
。
根据 official documentation 语法应如下所示:
from ..my_package import first
当我这样做时,出现以下异常:
Traceback (most recent call last):
File "/home/user/dev/root_dir/my_package/unit_tests/first.py", line 8, in <module>
from ..my_package import first
ImportError: attempted relative import with no known parent package
我还尝试使用以下语法导入文件:
from root_dir.my_package import first
当我这样做时,出现以下异常:
ModuleNotFoundError: No module named 'root_dir'
值得一提的是,我正在使用 pipenv
来处理虚拟环境。
知道为什么会这样吗?
谢谢。
我认为问题在于您的根目录不被视为 python 模块。
为了进行相对导入,您应该将“__init__.py”添加到您的根目录。
current working directory is not a package。用os.getcwd()
看看是什么,不过很有可能会是root_dir
.
这样的话,可以不用相对导入,直接按名称导入顶层包;你应该直接从 my_package
导入,像这样:
from my_package import first
...或者:
from my_package.first import do_something
复制的文件树:
root_dir
├── main.py
├── my_package
│ ├── __init__.py
│ └── first.py
└── unit_tests
├── __init__.py
└── test_first.py
main.py
的内容:
from unit_tests import test_first
if __name__ == "__main__":
test_first.test_something()
如果您尝试进行相对导入,即:from ..my_package import first
您将得到:
ImportError: attempted relative import beyond top-level package
首先,我将提供适合我的代码。然后,我会做一个简单的解释。这是一个简短的函数,可以让您从根目录导入。
解决方案
import os, sys
def access_root_dir(depth = 1):
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
args: list = [parent_dir]
for _ in range(depth):
args.append('..')
rel_path = os.path.join(*args)
sys.path.append(rel_path)
# At the top of test_first.py
access_root_dir(2)
import root_dir
由于根目录是 test_first.py
的祖父目录,您需要进入深度 2:
说明
我在我的一个项目中遇到了同样的问题并找到了
通过更改 sys.path
修复了从父目录导入的问题。使用类似的东西将绝对路径附加到根目录
sys.path.append(abs_path_to_root)
似乎不起作用,除非一切都是包的一部分。 Python 默认情况下不会访问导入中的父目录。
# Case 1: Relative path to parent - works
current_dir = os.path.dirname(os.path.realpath(__file__))
relative_path = os.path.join(current_dir, '..')
sys.path.append(relative_path)
import parent_module_name # This works for me (Python 3.9)
# Case 2: Absolute path to parent - Doesn't work
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
import parent_module_name # raises ModuleNotFoundError