Python相对路径导入

18

我有一个项目,在其中我想使用位于其他目录中的一些Python类。

示例结构:

/dir
 +../subdirA
 +../subdirB
 +../mydir

绝对路径因为这个项目在不同机器上运行而有所变化。

当我执行位于/mydir目录下的Python文件中的MySampleClass时,如何导入位于/dir/subdirA中的OtherClassRootOtherClassA

我尝试了以下方法:

from . import MySampleClass as msc
或者
from ../ import MySampleClass as msc

但是这总是失败或者给我错误信息,比如尝试在非包中进行相对导入

那么,相对导入Python文件的正确方式是什么?


1
你有读过 Python 文档中关于的部分吗?你也可以在这个答案中找到我发布的示例代码,可能会对你有所帮助。 - PM 2Ring
3个回答

23
你需要在mydir目录下创建一个名为__init__.py的文件(可以为空),然后只要dir在sys路径中,假设你的MySampleClass在myfile.py中且myfile.py在mydir中。
from mydir.myfile import MySampleClass

如果你想把位于subdirA下名为util.py的文件中的顶级函数导入到myfile.py(你的类所在的地方),那么subdirA中必须有一个__init__.py文件,然后在myfile.py中导入。

from subdirA.util import somefunc, someotherfunc

sys路径也是如此,即您必须从“dir”开始或添加它。从包的顶层(通常是您的项目文件夹)导入所有内容。

但是,对于模块测试,在解释器中可能会运行来自util的函数,如果您从subdirA开始,则需要添加dir到sys路径,以便您的导入可以解析。

>>> import sys
>>> sys.path.append('../dir')

但这只是一种hack方法,最好只在测试时从交互式解释器中使用。您还可以在.pth文件中将“dir”添加到您的网站包中。

要使用相对导入,您需要一个更深嵌套的文件夹,例如subdirA/subdirofA,然后在subdirofA中,您可以使用.来回退(如from .subdirB). 对我而言,相对导入有些难以看到其实用性。对我而言,更好的做法是使用相对于项目目录的直接导入,但如果您想嵌套一个天真的子包,那么我可以看到它们很有用,但仍然最好明确而不是含蓄的。

另请参见这里

针对Python 3的命名空间包进行更新。不再需要__init__.py文件。某些库仍可能引用该文件,因此可能仍需要保留以保持兼容性。例如:

(test-env) machine:~ user$ mkdir new_package
(test-env) machine:~ user$ python
>>> import new_package
>>> new_package.__file__
>>> type(new_package.__file__)
<class 'NoneType'>
>>>
(test-env) machine:~ user$ touch new_package/__init__.py
(test-env) machine:~ user$ python
>>> import new_package
>>> new_package.__file__
'/Users/user/new_package/__init__.py'
>>> type(new_package.__file__)
<class 'str'>
>>>

1
我想你可能误解了我的意思(或者是我表达得不够清楚^^):MySampleClass 位于 mydir 中并被执行。因此,我想将其他人的类从 subdirAsubdirB 等导入到 MySampleClass 中(位于 /mydir/myfile.py)。 - daniel451

2

首先将相对路径添加到PythonPath中。

import os

import sys

cwd = os.getcwd()

sys.path.append(cwd + '/../subdirA/')

sys.path.append(cwd + '/../subdirB/')

然后导入模块。

-2

目录结构如下:

/dir
 +../subdirA
 +../subdirB
 +../mydir

结合Linux命令ln,我们可以使事情变得更加简单:

1. cd dir/mydir
2. ln -s ../subdirA ./
3. ln -s ../subdirB ./

现在,如果你想从文件中导入some_stuffdir/subdirA/fileA.py到你的文件:dir/mydir/myfile.py,只需像这样导入:

from subdirA.fileA import some_stuff

同样的道理也适用于'dir/subdirB'

更重要的是,这对于setup.py进程也有效,:)


1
我们都知道可以用许多技巧来解决这个问题,例如:../__init__.py等。它们虽然有效,但并不够简单。我目前找到的最易维护和简单的方法是这种方式,期望能有更好、更简单的解决方案! - jacoolee

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