pythonic模块组织 - 如何引用根目录中的文件?

时间:2011-12-06 17:43:10

标签: python unix module pythonpath

我的python代码名为“project”,因此我的代码文件位于project / * .py中。我想在其中包含子模块,例如

project/code.py # where code lives
project/mymodule1  # where more code lives
project/mymodule2

每个模块目录都有自己的 init .py文件,例如

project/mymodule1/__init__.py

假设我在mymodule1(project / mymodule1 / test.py)中有一个文件“test.py”,我想引用“代码”中的某些内容,例如:导入函数“myfunc”

== project/mymodule1/test.py ==
from code import myfunc

问题是除非用户在他们的PYTHONPATH中放置了“project /”目录,否则将找不到“代码”。有没有办法避免这种情况,并使用某种“相对路径”来导入myfunc,例如

from ../code import myfunc

基本上,我不想强​​制代码的用户改变PYTHONPATH,除非我可以在我的脚本中以编程方式为它们做这件事。我希望它可以开箱即用。

如何做到这一点?解决方案是好的:以编程方式改变PYTHONPATH,或者更理想的是,使用某种相对导入来引用“代码”,因为即使我不知道用户的计算机上存在“project / code.py”的位置,我知道在哪里它与“myfunc”相关。

编辑:有人可以展示包内导入的正确示例吗?我试过,从“mymodule1”做:

from .. import foo

其中“foo”在code.py中,但它不起作用。我在mymodule1中有 init .py,所以:

project/code.py
project/mymodule1/__init__.py
project/mymodule1/module1_code.py

其中module1_code.py尝试导入foo,这是“code.py”中定义的函数。

编辑:我仍然存在的主要困惑是,即使采用响应我的消息给出的示例,显示项目/ sub1 /测试层次结构,您仍然无法“cd”到sub1并执行“python test.py”并让它工作。用户必须位于包含“project”的目录中,并执行“import project.sub1.test”。无论用户在哪个目录,我都希望这个工作。在这种情况下,用户必须执行文件“test.py”,它位于project / sub1 /中。所以测试用例是:

$ cd project/sub1
$ python test.py

产生错误:

ValueError: Attempted relative import in non-package

如何解决这个问题?

感谢。

2 个答案:

答案 0 :(得分:3)

这在Python 2.5及更高版本中是可行的。请参阅Intra-Package References上的文档。

有几点需要注意:

如果您希望用户在某处安装您的软件包,例如使用distutils或setuptools,那么project可能已经在搜索路径中,您可以更改相对导入from project.code import ...或类似。

如果您的用户正在将软件包安装到非标准目录(例如,他们的主目录,其他不在sys.path的其他位置等),我的意见是它会减少混淆指示用户修改PYTHONPATH而不是以编程方式更改sys.path

如果您不打算让用户安装代码 - 例如,他们只需要解密源代码,cd到project的父目录,然后运行脚本 - 然后包内引用和相对导入可能会正常工作。

编辑:根据请求,这是一个例子:

假设包布局如下:

project/
    __init__.py (empty)
    code.py
    sub1/
        __init__.py (empty)
        test.py

现在,project/code.py的内容是:

# code.py (module that resides in main "project" package)

def foo():
    print "this is code.foo"

而且,project/sub1/test.py的内容是:

# test.py (module that resides in "sub1" subpackage of main "project" package)

from ..code import foo
foo()

因此,test.py从相对路径foo导入名称..code,该路径使用包内引用将我们带回到code.py模块我们正在执行的..包的> parent (这是sub1.test部分)。

测试一下:

shell$ (cd to directory where "project" package is located)
shell$ python
Python 2.6.1 (r261:67515, Aug  2 2010, 20:10:18) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import project.sub1.test
this is code.foo

请注意,from .. import X语法中的双点只会将您带到父包,但您可以指定该包中的模块。

换句话说,在这种情况下,from .. import X相当于from project import X,因此X必须是project中的模块或类/函数/名称中的模块project/__init__.py

因此,from ..code import X相当于from project.code import X

答案 1 :(得分:1)

避免这种情况的最佳方法是将所有代码保存在src文件夹中,或者在项目中更好地命名,例如: myproject并保留__init__.py,以便您可以执行此操作

from myproject import code

所以您的文件夹结构将是

project
    main.py
    myproject
        __init__.py
        code.py
        module1
        module2

main.py或者你给它的任何名称都不应该有很多代码,它应该从myproject获得所需的模块并运行它。例如。

from myproject import myapp
myapp.run()

查看有关如何安排python项目的好article