我有一个具有以下目录结构的Python项目:
/(some files) /model/(python files) /tools/(more python files) ...
所以,我在几个子目录中有Python文件,还有一些 目录之间的依赖关系:工具由模型等使用。现在 我的问题是我想为模型和工具进行doctests, 我希望能够从命令行运行测试,如下所示: ./ model / car.py 。 我可以使这个工作,但只有凌乱的样板代码。我想要 知道什么是 正确的方法,还是有什么?
问题:我应该如何编写我的导入文件?
感谢名单。这是一个例子......
tools / tool.py 的内容:
#!/usr/bin/env python
"""
>>> is_four(21)
False
>>> is_four(4)
True
"""
def is_four(val):
return val == 4
if __name__ == '__main__':
import doctest
doctest.testmod()
...和 model / car.py :
#!/usr/bin/env python
"""
>>> car = Car()
>>> car.ok()
True
"""
from tools.tool import *
class Car(object):
def __init__(self):
self.tire_count = 4
def ok(self):
return is_four(self.tire_count)
if __name__ == '__main__':
import doctest
doctest.testmod()
通过在car.py的开头添加以下行,它可以工作,但看起来不太好。 :(
if __name__ == '__main__':
import sys
import os
sys.path.append(os.path.abspath(os.path.dirname('..')))
答案 0 :(得分:2)
您要做的是相对导入。它在Python中运行良好,但在模块级别,而不是在文件系统级别。我知道,这很令人困惑。
这意味着如果你在一个子目录中运行一个脚本,它就不会看到上层目录,因为对于正在运行的脚本,模块的根目录是当前目录:没有上层模块。
那么相对进口是什么?
嗯,只要它们是从上层导入的,就可以在上层目录中的子目录中导入模块。
在您的情况下,这意味着您必须从“/”运行脚本,以便它成为模块的根目录,并允许子模块使用相对导入。
问题的一个可能解决方案是删除if __name__ == "__main__"
块并创建/tests.py:
import doctest
from model import car
from tools import tool
doctest.testmod(car)
doctest.testmod(tool)
然后运行也启动所有测试。
最终你需要自动化这个过程,一个简单的解决方案是使用unittest,这样你就可以创建测试套件,只需添加你想要测试的模块名称:
import unittest
import doctest
modules = ("model.car",
"tools.tool")
suite = unittest.TestSuite()
for mod in modules:
suite.addTest(doctest.DocTestSuite(mod))
runner = unittest.TextTestRunner()
runner.run(suite)
另一种解决方案(推荐)是使用nose等工具为您自动执行此操作。
easy_install nose
nosetests --with-doctest # done :-)
顺便说一下,避免from x import *
。这适用于快速脚本,但是当程序增长时,您确实需要明确命名导入的内容。 import x
或from x import y
答案 1 :(得分:1)
使用包裹。将__init__.py
文件添加到您的工作目录和所有子文件夹,然后如果在当前目录中找不到该模块,您的导入将搜索父目录。
请参阅http://www.network-theory.co.uk/docs/pytut/Packages.html
此问题也与以下内容重复:
答案 2 :(得分:0)
不要以这种方式欺骗sys.path
。而是在调用$PYTHONPATH
时使用python
强制基本目录,或者使用该目录中的python -m model.car
。