从兄弟目录导入

42

我有一个名为"ClassA"的Python类,另外还有一个Python类"ClassB"想要导入"ClassA"。目录结构如下:

MainDir
../Dir
..../DirA/ClassA
..../DirB/ClassB

我该如何使用sys.path,以便ClassB可以使用ClassA?


2
它被称为相对导入,并且有相当多的可搜索材料和SO问题。 - user395760
https://dev59.com/0XVC5IYBdhLWcg3wfhGL - jgritty
3个回答

53

作为对“Python从父目录导入”问题的直接回答:

要导入当前模块父目录中的“mymodule”:

import os
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
os.sys.path.insert(0,parentdir) 
import mymodule

编辑 不幸的是,__file__属性并不总是被设置。 通过inspect模块获取父目录更加安全:

import inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)

1
Remi - 感谢您提供的直接答案。在编写 Python 应用程序的测试代码时,我发现这非常有用。我可以将测试代码放置在子目录中,并且可以开始放置测试而不修改现有项目。(换句话说,在放置测试之前将现有代码转换为模块是从管理引入错误风险的角度来看不正确的做法。)您更改模块路径的方法很方便。 - Heath Hunnicutt

31

您可以使用相对导入(来自链接的示例,当前模块为 A.B.C):

from . import D                 # Imports A.B.D
from .. import E                # Imports A.E
from ..F import G               # Imports A.F.G

4
@Yakattak:是的,但它们应该被放在一个包装里;) - user395760
这看起来是最好和最简单的答案。 - Rabih Kodeih
5
注意:相对导入依赖于模块的 __name__,因此如果您打算运行当前模块(将 __name__ 设置为 __main__),则相对导入将失败。请注意保持翻译后的内容与原文意思相同,但更加通俗易懂。 - Yibo Yang
什么是称之为包的标准?只需要每个子文件夹都包含一个__init__.py文件吗? - Sledge
@Sledge 它表示执行以下三个步骤:1)在代码的顶级目录中放置一个__init__.py文件;2)将顶级目录的父目录添加到您的PYTHONPATH中;3)在Python程序中设置__package__变量为包含__init__.py的目录的名称。 - AstroFloyd

17

你真的应该使用包。然后将MainDir放置在sys.path文件系统中的一个位置(例如.../site-packages),然后你可以在ClassB中这样写:

from MainDir.Dir.DirA import ClassA # which is actually a module

您只需在每个目录中放置名为__init__.py的文件,即可创建包层次结构。


我将MainDir添加到sys.path并尝试了您的解决方案,但它仍然显示没有名为MainDir.Dir.DirA的模块,并且所有目录中都有__init__.py文件。 - skylerl
3
不要添加MainDir,添加其父目录。如果您添加MainDir(如果它不是包根目录,那就没关系),则使用如下导入:from Dir.DirA import ClassA - Keith
我花了一些时间才明白“将你的代码打包”意味着 所有的 1) 在代码顶级目录中放置 __init__.py 文件,以及 2) 将顶级目录的父目录添加到你的 PYTHONPATH 中,并且 3) 在你的 Python 程序中设置 __package__ 变量为包含 __init__.py 的目录的名称。现在一切都正常了,谢谢! - AstroFloyd
如果ClassA.py代码定义了import ClassAA,其中ClassAA.py也在DirA中,那么当从ClassB导入ClassA时,上述方法会失败。在这种情况下,正确的方法是什么? - Phoenix
@Phoenix 使用相对导入 import .ClassAA,或在 ClassB 中使用 import ..DirA.ClassAA - Keith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接