11

给定以下 python 项目,在 PyDev 中创建:

├── algorithms
│   ├── __init__.py
│   └── neighborhood
│       ├── __init__.py
│       ├── neighbor
│       │   ├── connector.py
│       │   ├── __init__.py
│       │   ├── manager.py
│       │   └── references.py
│       ├── neighborhood.py
│       ├── tests
│       │   ├── fixtures
│       │   │   └── neighborhood
│       │   ├── __init__.py
│       └── web
│           ├── __init__.py
│           └── service.py
├── configuration
│   ├── Config.py
│   └── __init__.py
├── __init__.py
└── webtrack
    |- teste.py
    ├── .gitignore
    ├── __init__.py
    ├── manager
        ├── Data.py
        ├── ImportFile.py
        └── __init__.py

我们一直在尝试将模块从一个文件夹导入另一个文件夹,但没有成功,例如:

from algorithms.neighborhood.neighbor.connector import NeighborhoodConnector

产生结果:

Traceback (most recent call last):
File "teste.py", line 49, in <module>
from algorithms.neighborhood.neighbor.connector import NeighborhoodConnector
ImportError: No module named algorithms.neighborhood.neighbor.connector

我们尝试将其路径附加到 sys.path 变量,但没有成功。

我们还尝试使用 os.walk 将所有路径插入到 PATH 变量中,但仍然得到相同的错误,即使我们检查了 PATH 确实包含查找模块的路径。

我们在 Linux Ubuntu 13.10 上使用 Python 2.7。

我们有什么可能做错的吗?

提前致谢,

4

4 回答 4

14

在运行包中的脚本时正确导入是很棘手的。您可以阅读(遗憾地推迟的)PEP 395的这一部分,以了解对运行此类脚本不起作用的一堆方法的描述。

给出一个文件系统层次结构,如:

top_level/
    my_package/
        __init__.py
        sub_package/
            __init__.py
            module_a.py
            module_b.py
            sub_sub_package/
                __init__.py
                module_c.py
        scripts/
            __init__.py
            my_script.py
            script_subpackage/
                 __init__.py
                 script_module.py

只有几种方法可以使跑步my_script.py正常工作。

  1. 第一种是将top_level文件夹放入PYTHONPATH环境变量中,或者使用.pth文件来实现相同的目的。或者,一旦解释器运行,将该文件夹插入sys.path(但这会变得很难看)。

    请注意,您要添加top_level到路径中,而不是my_package! 我怀疑这是您在当前尝试此解决方案时遇到的问题。它很容易出错。

    然后,绝对导入 likeimport my_package.sub_package.module_a将大部分正常工作。(只是不要package.scripts.my_script在它作为模块运行时尝试导入自身__main__,否则你会得到一个奇怪的模块副本。)

    但是,绝对导入总是比相对导入更详细,因为您总是需要指定完整路径,即使您正在导入同级模块(或“侄女”模块,如module_cfrom module_a)。使用绝对导入,无论是哪个模块进行导入,获取module_c方式总是一大口难看的代码。from my_package.sub_package.sub_sub_package import module_c

  2. 出于这个原因,使用相对导入通常更优雅。唉,他们很难从脚本中开始工作。唯一的方法是:

    1. my_scripttop_level带有-m标志(例如)的文件夹运行,python -m my_package.scripts.my_script而不是通过文件名运行。

      如果您在不同的文件夹中,或者如果您使用不同的方法来运行脚本(例如在 IDE 中按 F5),它将不起作用。这有点不灵活,但实际上没有任何方法可以使它更容易(直到 PEP 395 被取消延迟并实施)。

    2. 设置sys.path为绝对导入(例如添加top_levelPYTHONPATH或其他内容),然后使用PEP 366 __package__字符串告诉 Python 脚本的预期包是什么。也就是说,my_script.py你想把这样的东西放在你所有的相对进口之上:

      if __name__ == "__main__" and __package__ is None:
          __package__ = "my_package.my_scripts"
      

      如果您重新组织文件组织并将脚本移动到不同的包,这将需要更新(但这可能比更新大量绝对导入工作少)。

    一旦你实现了这些解决方案之一,你的导入就会变得更简单。导入module_cmodule_a成为from .sub_sub_package import module_c. 在my_script中,类似的相对导入from ..subpackage import module_a将起作用。

于 2013-11-15T02:35:36.227 回答
0

只需__package__ = None每个.py 文件中设置。它将自动设置所有包层次结构。

之后,您可以自由地使用绝对模块名称进行导入。

from algorithms.neighborhood.neighbor.connector import NeighborhoodConnector
于 2014-10-26T12:56:35.460 回答
0

Python 2 和 3 中导入的工作方式略有不同。首先是 Python 3 和理智的方式(您似乎期望)。在 Python 3 中,所有导入都相对于其中的文件夹sys.path(有关模块搜索路径的更多信息,请参见此处)。顺便说一句, Python 不使用$PATH

因此,您可以从任何地方导入任何内容,而不必担心太多。

在 Python 2 中,导入是相对的,有时是绝对的。关于包的文档包含一个示例布局和一些可能对您有用的导入语句。

包内引用”部分包含有关如何在包之间导入的信息。

综上所述,我认为你的观点sys.path是错误的。确保包含 algorithms的文件夹(即不是 algorithms它本身,而是它的父文件夹)需要在sys.path

于 2013-11-14T08:44:55.243 回答
0

我知道这是一个旧帖子,但我仍然要发布我的解决方案。

有类似的问题。在导入包之前,只需添加以下行的路径:

sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 
from lib import create_graph
于 2017-05-02T18:42:10.483 回答