2

首先,这很可能不是路径问题。

我在 Eclipse 中有一个 pydev 项目。这是目录结构:

Genetic-Framework
  | Genetic-Framework
    | Genetic
      | __init__.py
      | GA.py
      | crossover.py
      | fitness.py
      | individual.py
      | mutation.py
      | population.py
      | selection.py
      | settings.py
      | visualization.py

GA.py中,我有以下行:

from Genetic import settings, selection, visualization as vis

是的,Geneticsys.path. 但是,我收到以下错误:

  File "/.../Genetic-Framework/Genetic-Framework/Genetic/GA.py", line 17, in <module>
    from Genetic import settings, selection, visualization as vis
ImportError: cannot import name settings

但是,当我settings从该行中删除时,其他所有内容都可以正常导入。

有趣的是,第一行settings.py是这样的:

from Genetic import fitness, selection, mutation, crossover, population, GA

当我GA从那条线上删除时,一切似乎都导入得很好。

为什么我会收到此错误?这是循环进口的问题吗?我怎样才能解决这个问题?

4

1 回答 1

4

是的,这是循环导入的问题。

问题

问题是,当你GA.py运行时,它首先尝试导入settings. 这意味着它settings.py开始运行,并立即尝试导入GA.

但是,GA已经在加载过程中,因此GA.py不会再次运行 - 相反,settings只是加载GA已经在内存中的(目前大部分是空的,因为它仍在执行其导入)。

因此,其中的事物settings尝试使用事物而GA不是失败,因为他们正在寻找的事物GA尚未定义(因为处理GA.py尚未通过导入)。

这使得对settings.pyraise的求值产生一个异常,表现为导入失败(因为import时抛出的异常导致导入失败)。

解决方案

a) 首先避免这种情况。

一般来说,您首先应该尽量避免循环导入。它们通常意味着你有非常奇怪的依赖结构,以后很难调试。

做到这一点的一种方法是尝试找到两个模块中需要的东西,并将它们分解成一个单独的第三个模块,可以在其他两个模块之间共享 - 所以不要在 B 中使用 Ax,在 A 中使用 By,而是在 A 和 B 中都使用 Cx 和 Cy。

b) 在加载所有内容之前,不要真正尝试使用循环导入中的内容。

您可以做的另一件事是将其他模块的某些内容的使用推迟到所有导入完成之后。换句话说,不要尝试从顶级代码中引用导入模块的内容,而是将其放在类初始化程序或稍后可以在所有导入完成后调用的函数中。

例如,而不是这个......

import Foo

class Baz:
    top_level_variable = Foo.bar

你可以这样做:

import Foo

class Baz:
    def __init__(self):
        self.instance_variable = Foo.bar

显然,实例属性与类属性略有不同,但其想法是将实际必须从其他模块中查找内容的时间推迟到所有模块完成执行并因此它们的内容可用之后。另请注意,from Foo import bar此处会失败,因为它会尝试Foo在导入时访问 的内容,这是需要避免的。

于 2012-11-18T21:46:20.373 回答