2010-12-03 144 views
70

首先关闭所有:我很抱歉,我知道有很多关于相对进口的问题,但我没有找到解决方案。如果可能的话,我想用下面的目录布局:蟒蛇包装相对进口

myClass/ 
    __init__.py 
    test/ 
     demo.py 
     benchmark.py 
     specs.py 
    src/ 
     __init__.py 
     myClass.py 

现在我的问题是:

  • 如何从包装内的测试文件正确导入myClass.py?

  • 如果您将myClass作为子模块放在libs/myClass或include/myClass中,您将如何从外部导入软件包?

到目前为止,我找不到一个优雅的解决方案。从我的理解Guido's Decision应该可以做到from ..src import myClass但这将错误:

ValueError: Attempted relative import in non-package

它看起来,因为它没有把myClass的为包。 Reading the docs

​​

我似乎失去了一些东西,它指定包的脚本,我应该使用.pth?

+6

@布伦特纽维,是的,你是对的,相对进口似乎是一个持续的话题,在阅读了不少答案之后,我仍然觉得有专门描述我的情况的冲动。在展示了这个q之后,在#python IRC频道中,不少人推荐使用平面目录结构:“许多人拒绝Python想用目录和文件获取语义名称空间信息的方式,最好只是放弃并做Python想要什么。“ http://jcalderone.livejournal.com/39794.html – eerne 2010-12-03 18:24:45

+8

任何人都可以提供一个链接到一些真实世界的软件包,示例性的目录布局,或遵循一些约定? (理想情况下在github上) – eerne 2010-12-03 18:31:07

+1

在`test`目录中是否有`__init __。py`? `ValueError:试图在非包中进行相对导入可能与它有关。 – jfs 2010-12-03 20:48:58

回答

0

Intra-package-references描述如何从test/*myClass。要从外部导入软件包,应在运行导入器应用程序之前将其路径添加到PYTHONPATH环境变量中,或在导入之前将其路径添加到代码中的sys.path列表中。

为什么from ..src import myClass失败:可能,src不是python包,不能从那里导入。如上所述,您应该将其添加到python路径。

41

ValueError: Attempted relative import in non-package

表示您尝试在不是包的模块中使用相对导入。它与这个from ... import声明的文件有关的问题,而不是您要导入的文件。因此,如果您在测试中执行相对导入操作,例如,您应该使测试成为您的软件包的组成部分。这意味着

  1. 添加__init__.py测试/
  2. 一些外界的脚本来运行它们,就像nosetests

如果你运行的东西为python myClass/test/demo.py,因为你正在运行演示模块相对导入不会太没有包装。相对导入要求使用它们的模块自身以包模块from myClass.test.demo import blabla或相对导入的方式导入。

25

昨晚经过数小时的搜索后,我找到了python中相对导入的答案!或者至少是一个简单的解决方案。解决这个问题的最好方法是从另一个模块调用模块。因此,假设您希望demo.py将myClass.py 导入子包的根目录下的MyClass文件夹中,需要有一个文件调用其他两个文件。从我收集的工作目录总是被认为是主要所以如果你用demo.py脚本测试从demo.py导入,你将会收到这个错误。为了说明:

夹hierarcy:

myClass/ 
    main.py #arbitrary name, can be anything 
    test/ 
     __init__.py 
     demo.py 
    src/ 
     __init__.py 
     myClass.py 

myClass.py:

def randomMaths(x): 
    a = x * 2 
    y = x * a 
    return y 

demo.py:

from ..src import myClass 

def printer(): 
    print(myClass.randomMaths(42)) 

main.py:

import test.demo 

demo.printer() 

如果你在解释器中运行demo.py,你会产生一个错误,但是运行main.py不会。这有点复杂,但它的工作原理:D