我有以下内容:
ModuleFolder
|
|-->. ModuleFile.py .
|
'-->. TestsFolder .
|
'---> UnitTest1.py
我尝试从父目录导入。在这种情况下,我试图运行" UnitTest1.py"从测试文件夹中导入,并从其正上方的目录导入(文件" ModuleFile.py")。
from .. import *
的文档,但我特意尝试import MyModuleName
,因此我可以在单元测试中更明确,避免名称的错误/冲突。我在做什么(它对我有用)如下:
sys.path.append("../")
然后从父目录导入我需要的内容。
sys.path
?因为它是相对的。如果我从/ home / workspace / MyModule / unittests /运行并且我的模块位于/ home / workspace / MyModule /我假设将/ home / workspace / MyModule /添加到路径中,如果是同事则必然是真的在他自己的/ home / documents / MyModule目录下运行它。我的问题:
这是Python适当的吗?如果没有,这有什么不对。有没有更好的办法?或者这真的是一个RTFM时刻,答案是我已经看过的7个以上SO问题之一? (我看到那些都推荐了明确的路径而不是我采用的相对路径方法。)
其他有用信息:
答案 0 :(得分:26)
不要从tests文件夹运行测试。从项目的根目录运行它,该目录是模块文件夹。您应该很少需要使用 <{em> sys.path
或PYTHONPATH
进行捣乱,当您这样做时,您要么会导致其他图书馆出现错误,要么让生活变得更艰难你的用户。
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
(始终从模块外部)执行它