2009-08-27 144 views
9

好的,我认为无论我做错了什么,它可能是非常明显的,但我无法弄清楚。我已经阅读并重新阅读了关于包的教程部分,我唯一能想到的是这不会起作用,因为我直接执行它。这里的目录设置:Python软件包?

eulerproject/ 
    __init__.py 
    euler1.py 
    euler2.py 
    ... 
    eulern.py 
    tests/ 
    __init__.py 
    testeulern.py 

这里是testeuler12.py的内容(第一测试模块我已经写了):

import unittest 
from .. import euler12 

class Euler12UnitTests(unittest.TestCase): 


    def testtriangle(self): 
     """ 
     Ensure that the triangle number generator returns the first 10 
     triangle numbers. 

     """ 
     self.seq = [1,3,6,10,15,21,28,36,45,55] 
     self.generator = euler12.trianglegenerator() 
     self.results = [] 
     while len(self.results) != 10: 
      self.results.append(self.generator.next()) 
     self.assertEqual(self.seq, self.results) 

    def testdivisors(self): 
     """ 
     Ensure that the divisors function can properly factor the number 28. 

     """ 
     self.number = 28 
     self.answer = [1,2,4,7,14,28] 
     self.assertEqual(self.answer, euler12.divisors(self.number)) 


if __name__ == '__main__': 

    unittest.main() 

现在,当我从IDLE和命令执行此线,而在目录中,我得到以下错误:

Traceback (most recent call last): 
    File "C:\Documents and Settings\jbennet\My Documents\Python\eulerproject\tests\testeuler12.py", line 2, in <module> 
    from .. import euler12 
ValueError: Attempted relative import in non-package 

我认为这个问题是因为我直接运行它,我不能做的相对进口(因为__name__变化,我含糊对软件包描述的理解是,__name__是它如何知道它在哪个软件包中的一部分),但是在那种情况下,你们如何导入从测试代码上级存储的'生产'代码?

+0

只需选择它并点击代码示例按钮。或者将它包装在'' – 2009-08-27 18:52:04

回答

8

通常你会有一个目录,其名称是你的包名称,在你的PYTHONPATH的某个地方。例如:

eulerproject/ 
    euler/ 
     __init__.py 
     euler1.py 
     ... 
     tests/ 
      ... 
    setup.py 

然后,您可以安装此系统范围,或确保调用脚本时设置PYTHONPATH=/path/to/eulerproject/:$PYTHONPATH

像这样的绝对导入,然后将工作:

from euler import euler1 

编辑

根据Python文档,“打算用作一个Python应用程序应该使用的主要模块模块绝对进口“。 (Cite

因此,像其他答案中提到的nose这样的测试工具可以工作,因为它会导入包而不是从命令行运行它们。

如果你想手工做的事情,你可运行脚本需要在封装层次外,像这样:

eulerproject/ 
    runtests.py 
    euler/ 
     __init__.py 
     euler1.py 
     ... 
     tests/ 
      __init__.py 
      testeulern.py 

现在,runtests.py可以做from euler.tests.testeulern import TestCasetesteulern.py可以做from .. import euler1

+2

是的,但是你的项目不再利用相对的进口。相对导入的好处在于它使您的软件包自成一体。它不依赖于它的主文件夹名称,也不能错误地导入某个单元,例如,被埋在PYTHONPATH某处的过时版本的软件包。 – 2009-08-27 19:11:06

+0

好的,那么在调用脚本之前我将如何设置PYTHONPATH?就像我希望能够在同一台计算机上的两个不同位置运行一样? ps:我也在学习如何处理与mercurial的克隆/合并,这就是为什么它在两个地方。 – Jonathanb 2009-08-27 19:18:33

+0

如果从位于程序包层次结构之外的脚本导入模块,则添加关于相对导入如何工作的注释。否则,请使用测试工具。 设置环境变量取决于你在做什么。如果你使用bash,只需做PYTHONPATH = foo python scriptname.py – 2009-08-27 19:23:02

10

我有同样的问题。我现在使用nose来运行我的测试,并正确处理相对导入。

是的,这整个相对重要的东西是混乱。

+2

我正在接受其他答案,因为它可以让我执行我一直在尝试使用相对导入的方法。然而,我也下载鼻子作为我的测试用具,因为它看起来比我可以自己拼凑起来的任何东西都强大得多。 – Jonathanb 2009-08-27 19:52:14

+0

正是我所寻找的,谢谢 – Copperfield 2017-02-27 19:16:29