从父目录导入Python

时间:2013-10-29 20:45:15

标签: python

我有以下内容:

         ModuleFolder
              |
              |-->. ModuleFile.py .
              |
              '-->. TestsFolder .
                         |
                         '---> UnitTest1.py

我尝试从父目录导入。在这种情况下,我试图运行" UnitTest1.py"从测试文件夹中导入,并从其正上方的目录导入(文件" ModuleFile.py")。

  • 我知道已经有很多答案了。 SO Question1SO Question2Every Other SO Question。我只是无法找到"使用../"作为相对导入而不是显式路径。
  • 我知道,从Python 2.5开始,他们支持"相对导入"根据提到使用from .. import *的文档,但我特意尝试import MyModuleName,因此我可以在单元测试中更明确,避免名称的错误/冲突。

我在做什么(它对我有用)如下:

sys.path.append("../")

然后从父目录导入我需要的内容。

  • 是的,父目录中有__init__.py,
  • 不,我的父路径不是Python路径或环境变量的一部分
  • 为什么我不将父路径添加到sys.path?因为它是相对的。如果我从/ home / workspace / MyModule / unittests /运行并且我的模块位于/ home / workspace / MyModule /我假设将/ home / workspace / MyModule /添加到路径中,如果是同事则必然是真的在他自己的/ home / documents / MyModule目录下运行它。

我的问题:

这是Python适当的吗?如果没有,这有什么不对。有没有更好的办法?或者这真的是一个RTFM时刻,答案是我已经看过的7个以上SO问题之一? (我看到那些都推荐了明确的路径而不是我采用的相对路径方法。)

其他有用信息:

  • Python 2.6
  • 在Linux上工作但可以轻松跳转到Win。

6 个答案:

答案 0 :(得分:26)

不要从tests文件夹运行测试。从项目的根目录运行它,该目录是模块文件夹。您应该很少需要使用 <{em> sys.pathPYTHONPATH进行捣乱,当您这样做时,您要么会导致其他图书馆出现错误,要么让生活变得更艰难你的用户。

python -m TestsFolder.UnitTest1

如果您使用像py.test这样的测试运行器,您只需从结帐的根目录运行py.test即可找到适合您的测试。 (假设您将测试命名为更像test_unit1.py。您当前的命名方案有点不正统。;))

答案 1 :(得分:5)

最好在sys.path的开头插入相对路径,如下所示:

import sys
sys.path.insert(0, '../')

答案 2 :(得分:2)

我的建议是:

不要试图聪明,做你应该做的事。即确保您的模块和软件包位于Python路径中的某个位置。

最简单的方法是在用于执行脚本的shell中设置环境变量PYTHONPATH:

$ export PYTHONPATH=/the/directory/where/your/modules/and/packages/are
$ cd /the/directory/where/your/unit/tests/are
$ python test1.py

答案 3 :(得分:2)

使您的测试文件夹成为一个模块(通过添加 __ init __。py ) 然后,您可以在项目主页中使用run python -m tests.test_name或使用以下 Makefile

TEST_FILES = $(wildcard tests/test_*.py)
TESTS = $(subst .py,,$(subst /,.,$(TEST_FILES)))
all.PHONY: test
test:
    @- $(foreach TEST,$(TESTS), \
        echo === Running test: $(TEST); \
        python -m $(TEST); \
        )

答案 4 :(得分:0)

您还可以创建要导入的模块路径的符号链接,然后使用该符号链接进行导入。在python dist-packages中创建一个符号链接。

创建符号链接:

ln -s "/path/to/ModuleFolder" "/path/to/python/dist/packages/module_symlink_name"

要在脚本中导入模块:

from module_symlink_name import ModuleFile

无需导出python路径或修改sys路径。

答案 5 :(得分:0)

这总是很令人困惑。相对导入是相对于模块结构的。要测试相对导入,您需要在主文件中(从模块外部)导入您的模块。让我尝试展示一个有效的案例:

$ python use_module.py
Hello World!

或者您可以将其设为可执行模块并使用 python -m 运行它(始终从模块外部)

$ python -m module.child_a
Hello World!

结构

test_module.py
module
├── __init__.py [can be empty]
├── child_a
   ├── __init__.py
   ├── __main__.py
│── child_b
   ├── foo.py

test_module.py

from module.child_a import message
print(message)

foo.py

phrase = "Hello World"
mark = '!'

child_a/__init__.py

from .__main__ import message

child_a/__main__.py

from .. child_b.foo import phrase, mark

message = phrase + mark

if __name__ == "__main__":
    #this block is run when executing `python -m module.etl`

    print(message)

注意:如果您在 child_a 中添加另一个文件,例如 child_a/myscript.py,您仍然可以使用 python -m module.sub_a.myscript(始终从模块外部)执行它