【问题标题】:In Python, how can I import from a grandparent folder with a relative path?在 Python 中,如何从具有相对路径的祖父文件夹导入?
【发布时间】:2018-06-27 16:31:33
【问题描述】:

想象一个文件夹结构如下:

project/
    grandparent.py
    folder1/
        parent.py
        folder2/
            sibling.py
            current.py

如果我在current.py 我可以从其他文件using relative paths 导入如下:

from .sibling import *
from ..parent import *

如何从grandparent.py 导入?

(我试过...grandparent../..grandparent

【问题讨论】:

  • 将它们制作成 python 包,而不是普通目录,您将能够使用 import,例如:import grandparent.folder1.parent
  • 为了澄清,@NickRyan 是说:“按照 ZYYYY 下面所说的去做”。这就是制作 python 包所需要的全部内容。
  • @MikeWilliamson 可能会编辑该答案以包含您的有用笔记
  • 是的,你是对的@d3vid。完成!

标签: python python-3.x python-import relative-path


【解决方案1】:

创建 Python 包

作为确保某种程度的安全性的一种手段 - 以便 Python 模块无法访问它们不受欢迎的区域 - 通常禁止从父母或祖父母导入...除非您创建包

幸运的是,在 Python 中,创建一个包非常容易。您只需在要视为包的一部分的每个文件夹/目录中添加一个__init__.py 文件。而且,__init__.py 文件甚至不需要包含任何内容。您只需要存在(可能为空的)文件。

例如:

#current.py

from folder1.grandparent import display

display()

#grandparent.py
def display():
    print("grandparent")

# ├── folder1
# │   ├── __init__.py
# │   ├── folder2
# │   │   ├── __init__.py
# │   │   └── folder3
# │   │       ├── __init__.py
# │   │       └── current.py
# │   └── grandparent.py

后续步骤

这不是 OP 的问题,但高度相关且值得一提:如果您导入 目录 而不是模块(文件),那么您正在导入 __init__.py 文件。例如,

import folder1

实际上是在folder1目录中执行__init__.py文件的导入。

最后,双下划线经常被使用,它被缩短为dunder。所以说话的时候可以说“dunder init”来指代__init__.py

【讨论】:

  • 要清楚,如果有人是新人:@ZYYYY 在作为包的一部分的每个文件夹级别添加了那些 __init__.py 文件。只要这些文件存在,它们就可以完全为空。通过添加它们,您使包“可遍历”,您可以如图所示导入。最后说明:在某些情况中使用 Python 3,您不需要存在 __init__.py 文件。但请使用它们; (a) 它使您的代码对遗留 Python 更友好,(b) 其他人清楚什么是包的一部分,以及 (c) 甚至 Python 3 也无法完全遍历,就像在这个祖父母案例中一样。
  • 文件夹 1 是否必须在 sys.path 中?
  • 我尝试了答案,但没有奏效。但是在将文件夹 1 添加到 sys.path 后它确实有效。这是强制性步骤吗?
【解决方案2】:

当前.py

import os
import sys
FILE_ABSOLUTE_PATH = os.path.abspath(__file__)  # get absolute filepath
CURRENT_DIR = os.path.dirname(FILE_ABSOLUTE_PATH)  # get directory path of file
PARENT_DIR = os.path.dirname(CURRENT_DIR)  # get parent directory path
BASE_DIR = os.path.dirname(PARENT_DIR)  # get grand parent directory path
# or you can directly get grandparent directory path as below
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

sys.path.append(BASE_DIR)  # append the path to system
import grandparent
from folder1 import parent  # this way you can import files from parent directory too instead of again appending it to system path

【讨论】:

  • 最好不要乱用实际路径名,而是添加__init__.py文件,就像上面提到的@ZYYY。
  • @MikeWilliamson 这并没有弄乱实际路径,这是许多模块喜欢使用的方式,而不是担心初始化文件。如果您看起来这只是获取文件的当前/父目录的一种方法
猜你喜欢
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-22
  • 2019-11-02
  • 2022-07-19
相关资源
最近更新 更多