首页 > 解决方案 > Python + 子模块:ImportError:尝试使用没有已知父包的相对导入

问题描述

我一直在为 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.

根据官方文档,语法应该如下:

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来处理虚拟环境。知道为什么会这样吗?

谢谢。

标签: pythonpython-3.xgit-submodulespython-modulepipenv

解决方案


首先,我将为您提供对我有用的代码。然后,我将做一个简短的解释。这是一个简短的函数,可以让您从根目录导入。

解决方案

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

推荐阅读