简体   繁体   English

无法导入模块

[英]Can't Import Module

First of all, this is very likely not a path issue. 首先,这很可能不是路径问题。

I have a pydev project in eclipse. 我在Eclipse中有一个pydev项目。 Here is the directory structure: 这是目录结构:

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

In GA.py , I have the following line: GA.py ,我有以下内容:

from Genetic import settings, selection, visualization as vis

And yes, Genetic is in sys.path . 是的, Geneticsys.path However, I get the following error: 但是,出现以下错误:

  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

However, when I remove settings from that line, everything else imports just fine. 但是,当我从该行删除settings时,其他所有内容都可以正常导入。

Interestingly, among the first lines of settings.py is this: 有趣的是,在settings.py的第一行中是这样的:

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

And when I remove GA from that line, everything seems to import just fine. 当我从该行中删除GA时,一切似乎都可以正常导入。

Why am I getting this error? 为什么会出现此错误? Is this some issue with circular imports? 循环进口是否有此问题? How can I fix this? 我怎样才能解决这个问题?

Yes, that's an issue with circular imports. 是的,这是循环进口的问题。

The problem 问题

The problem is that when your GA.py is run, it first tries to import settings . 问题在于,当您运行GA.py时,它将首先尝试导入settings This means that settings.py starts getting run, and it immediately tries to import GA . 这意味着settings.py开始运行,并立即尝试导入GA

However, GA is already in the process of loading, so GA.py doesn't get run a second time - instead, settings just loads the GA that is already in memory (which is currently mostly empty, because it's still executing its imports). 但是, GA已经在加载过程中,因此GA.py不会GA.py运行-而是, settings仅加载内存中已经存在的GA (当前大部分为空,因为它仍在执行导入操作) 。

Thus, things in settings that try to use things out of GA fail, because the things they're looking for in GA haven't been defined yet (because processing of GA.py hasn't gotten past the imports yet). 因此,尝试在GA使用事物的settings中的事物将失败,因为尚未定义他们在GA寻找的事物(因为GA.py处理尚未超出导入范围)。

This makes the evaluation of settings.py raise an exception, which manifests as a failure to be imported (because an exception raised during import makes the import fail). 这将使settings.py的评估引发异常,表现为导入失败(因为在导入过程中引发的异常使导入失败)。

The solution 解决方案

a) Avoid the situation in the first place. a)首先避免这种情况。

In general, you should try to avoid circular imports in the first place. 通常,应该首先避免循环导入。 They often mean that you have really odd dependency structure that will be hard to debug later. 它们通常意味着您具有非常奇怪的依赖关系结构,以后很难调试。

One way to do this is to try to find things that are needed in both modules and break them out into a separate third module that can be shared between the other two - so instead of using Ax in B, and By in A, you instead use Cx and Cy in both A and B. 执行此操作的一种方法是尝试找到两个模块中都需要的东西,并将它们分解为可以在其他两个模块之间共享的单独的第三个模块-因此,您不必在B中使用Ax,而在A中使用By在A和B中同时使用Cx和Cy。

b) Don't actually try to use things from circular imports until everything's loaded. b)在装入所有内容之前,不要真正尝试使用循环导入中的内容。

Another thing you can do is to defer usage of something from another module until after all of the imports have finished. 您可以做的另一件事是将所有模块中的某些东西的使用推迟到所有导入完成之后。 In other words, don't try to reference an imported module's contents from top-level code, but instead place it in a class initializer or a function that you can call later on, once all of the imports have finished. 换句话说,不要尝试从顶级代码中引用导入模块的内容,而应将其放置在类初始化器或函数中,一旦所有导入完成,便可以稍后调用该函数。

For example, instead of this... 例如,代替这个...

import Foo

class Baz:
    top_level_variable = Foo.bar

you can do this: 你可以这样做:

import Foo

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

Obviously, instance properties are slightly different from class properties, but the idea is to defer actually having to look things up from other modules until after all of the modules finish executing and thus have their contents available. 显然,实例属性与类属性略有不同,但其想法是推迟实际从其他模块中查找内容的过程,直到所有模块完成执行并因此使其内容可用为止。 Also note that from Foo import bar would fail here because that tries to access the contents of Foo at the time of the import, which is what needs to be avoided. 还要注意, from Foo import bar在这里会失败,因为这会尝试在导入时访问Foo的内容,这是需要避免的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM