21

我有以下内容:

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

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

  • 我知道已经有很多答案了。 SO Question1SO Question2每隔一个 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 问题之一中?(我看到那些都推荐显式路径而不是我采用的相对路径方法)。

其他有用信息:

  • 蟒蛇2.6
  • 在 Linux 中工作,但也可以轻松跳到 Win。
4

6 回答 6

28

不要从测试文件夹运行测试。从项目的根目录运行它,即模块文件夹。您应该很少需要使用 sys.pathor PYTHONPATH,当您这样做时,您要么给其他库造成错误,要么让用户的生活更加艰难。

python -m TestsFolder.UnitTest1

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

于 2013-10-29T21:44:03.497 回答
5

最好在这样的开头插入您的相对路径sys.path

import sys
sys.path.insert(0, '../')
于 2013-10-29T21:27:24.647 回答
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
于 2013-10-29T20:56:22.277 回答
2

使您的测试文件夹成为一个模块(通过添加__init__.py)。然后,您可以在项目主页
中使用 runpython -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); \
        )
于 2015-04-21T16:47:00.623 回答
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 路径。

于 2017-11-15T08:42:35.753 回答
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

于 2021-03-11T18:41:28.443 回答