子模型名称与文件相同的Python模块布局

时间:2014-07-23 05:14:29

标签: python packages

我已经习惯了一种脚本语言,在这种语言中布局这样的模块很常见:

lib/Foo.pm
lib/Foo/Bar.pm
lib/Foo/Baz.pm

如果你有Foo.pm,那么有一个名为Foo的目录,你可以在其下放置子模块。

在Python中,我试图像这样模仿布局:

modules/foo.py
modules/foo/bar.py
modules/foo/baz.py

然而,这不会起作用,因为当我这样做时:

from foo import Foo

Python认为我正在导入一个名为' foo'的目录。而不是foo.py.我试图弄乱 init .py业务无济于事。

有没有办法解决这个问题?我发现Python无法区分目录foo和文件foo.py。

,这很令人讨厌

编辑: 我想我错过了一件重要的事情。我通过单元测试来获取modules /目录,因此整个目录结构如下所示:

modules/foo.py
modules/foo/bar.py
modules/foo/baz.py
tests/unit.py

在unit.py中,我有以下内容:

#!/usr/bin/python

import sys
import os

findbin = os.path.abspath(os.path.dirname(sys.argv[0]))
sys.path.append(findbin + "/../modules")

from foo import Foo

obj = Foo()

当我跑步时,我得到:

from foo import Foo
ImportError: cannot import name Foo

3 个答案:

答案 0 :(得分:5)

您要创建的是包。

文件夹foo中的

放置一个名为__init__.py的空白文件。然后Python会将foo视为一个包。如果modules也被视为一个包,也会在其中放置一个空白的__init__.py

所以从你的问题来看,如果包正确完成并且你有这个结构:

modules/__init__.py
modules/foo/__init__.py
modules/foo/bar.py
modules/foo/baz.py

你可以这样做:

import module
from module import foo
from module.foo import bar
import module.foo.bar as foobar

还有很多其他的东西!

答案 1 :(得分:1)

必须这样做:

modules/foo/__init__.py  # instead of foo.py
modules/foo/bar.py
modules/foo/baz.py

Perl的布局不起作用;如果一个模块有孩子,那么根就和他们一起生活。

对于它的价值,一些Python开发人员强烈认为你应该将__init__.py留空(或至少是最小的),因为它会在你导入任何一个孩子的时候首先导入

如果__init__.py没有为您效果,您可能还会遇到其他问题,特别是如果您确实有modules/目录,但我可以& #39; t诊断没有更多细节:)


啊哈。 不要惹恼sys.path; 总是这标志着你让自己的生活变得更加艰难。 (您是否需要使用sys.path来导入其他任何人的代码?那么为什么您必须为自己做这件事,当它在那里时?)

只需将它们直接放在源树的根目录中,即project.git/foo/bar.py。只要您从根运行测试工具(或其他任何工具),就可以毫无问题地导入它们。

您可能还想尝试像pytest这样的测试库,它可以为您进行发现和各种奇特的事情。

另请参阅:Filesystem structure of a Python project

或者是我的一个小项目,以获得更实际的例子:https://github.com/eevee/dywypi

答案 2 :(得分:0)

使用Python创建包可以使用__init__.py文件完成,但了解导入优先级非常重要。命令

from foo import Foo

将在foo中查找名为sys.path的内容,然后查找名为Foo"内部" foo。例如,假设您的目录__init__.py中没有任何foo个文件,并且您的foo.py文件包含,

class Foo:
    def __init__(self):
        print 'hello'

从模块目录中发出命令from foo import Foo将起作用。

>>> from foo import Foo
>>> f = Foo()
hello

如果您希望目录foo是一个包(即相关模块的集合),那么您可以在__init__.py目录中放置一个空的foo文件。但是这会使import命令变得模糊不清。我还没有发现声明包具有比模块更高的导入优先级的任何文档,但您可以通过执行以下操作来验证Python是否正在导入包,

import foo
>>> foo.__file__
foo/__init__.py

表示包已导入。我认为包装优先的事实并非总是如此。最后,最好通过重命名文件或包来删除名称冲突。