7

我的 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”,我想从“code”中引用一些东西,例如导入函数“myfunc”

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

问题是除非用户将“project/”目录放在他们的 PYTHONPATH 中,否则找不到“code”。有没有办法避免这种情况并使用某种“相对路径”来导入 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”中定义的函数。

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

$ cd project/sub1
$ python test.py

这会产生错误:

ValueError: Attempted relative import in non-package

如何解决?

谢谢。

4

2 回答 2

4

这在 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..codecode.py..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

于 2011-12-06T18:11:57.837 回答
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 项目的好文章。

于 2011-12-06T18:12:55.010 回答