2011-03-04 49 views
8

我在构建我的python项目时遇到了一些问题。目前它是一堆文件在同一个文件夹中。我试图把它的结构像测试和python包结构

proj/ 
    __init__.py 
    foo.py 
    ... 
    bar/ 
    __init__.py 
    foobar.py 
    ... 
    tests/ 
    foo_test.py 
    foobar_test.py 
    ... 

问题是,我不能从内部目录,从外部目录导入模块。这对测试尤其恼人。

我已阅读关于相对进口的PEP 328和关于从主模块进行的相对进口的PEP 366。但是这两种方法都需要基础包装在我的PYTHONPATH中。事实上,我得到以下错误

ValueError: Attempted relative import in non-package.

所以我添加的测试文件

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 

我仍然得到同样的错误的顶部以下样板代码。什么是正确的方式来

  • 结构的包,完成测试,并
  • 增加的基本目录,以允许进口的路径?

编辑作为评论的要求,我想补充一个例子导入失败

import os, sys 
sys.path.append(os.path.join(os.getcwd(), os.path.pardir)) 
from ..foo import Foo 
+0

可以显示导入失败的示例吗? –

+0

此外,请为您的'PYTHONPATH' –

+0

'echo $ PYTHONPATH'包含值现在只是空的。 – Andrea

回答

12

当您使用-m切换器来运行代码时,当前目录被添加到sys.path。因此,要运行测试的最简单的方法是从proj父目录,使用以下命令:

python -m proj.tests.foo_test 

为了使这项工作,你将需要包括一个__init__.py文件在您的测试目录中,以便测试是正确的确认为包装的一部分。

+0

谢谢!所以我错过了''测试'本身应该是一个包。这是一个相当愚蠢的错误,但我无法弄清楚。 – Andrea

5

我喜欢使用完整的proj.NAME包前缀尽可能导入模块(文件foo_test.py中)。这是Google Python styleguide推荐的方法。

允许您保留包结构,使用完整包路径,并继续前进开发的一个选择是使用virtualenv并将项目置于开发模式。您的项目setup.py将需要使用setuptools而不是distutils,以获取develop命令。

这将让你避免sys.path.append东西上面:

% virtualenv ~/virt 
% . ~/virt/bin/activate 
(virt)~% cd ~/myproject 
(virt)~/myproject% python setup.py develop 
(virt)~/myproject% python tests/foo_test.py 

其中foo_test.py用途:

from proj.foo import Foo 

现在,当你从你的virtualenv您PYTHONPATH中运行python将指向所有的软件包在你的项目中。你可以创建一个更短的shell别名来输入你的virtualenv,而不必每次输入. ~/virt/bin/activate

+0

这似乎很有趣。我将不得不调查这个virtualenv工具。它是否允许我在虚拟环境中工作,以便可以将当前目录作为一个包进行访问?或者它只是一个带有独立python发行版的工具 - 更像是一个chroot--我必须在每次使用它之前安装我的软件包? – Andrea

+0

这是一种创建独立Python环境的快速方法,可以快速删除并重新创建。适合尝试使用pip/easy_install模块而不会污染您的系统Python。 virtualenv'activate'脚本将'〜/ virt/bin'目录插入PATH的前面,以便在系统python之前找到〜/ virt/bin/python。 'develop'命令使用'.pth'文件将项目的包链接到'〜/ virt/lib/pythonx.x/site-packages'中。它还修改了'PS1'提示,让你知道你是在虚拟内部的“内部”。 – samplebias

+0

很好的建议,尽管现在你可能想选择'distribute'作为'setuptools'的一个更积极维护的替代品。 – ncoghlan