【问题标题】:How to solve infinite loop import?如何解决无限循环导入?
【发布时间】:2020-05-18 18:45:52
【问题描述】:

我想了解我的问题的根源。我遇到过几次这种情况,每次都想出来很费时间。

这一次我觉得我错过了一些我认为我理解的东西。 相关问题贴在这里:Infinite loop with Python imports; looking for Pythonic way

我决定我的模块存在无限循环,但我仍然遇到同样的错误。所以这就是我所拥有的。 我在这里也包含了__init__.py 文件,因为我怀疑这个文件可能会导致我目前不知道的行为。

sources/preparation/features/__Init__.py:

from .build_features import *
from .get_qualified_edges import *
from .select_strategy import *
from .test import *

sources/preprocessing/__init__.py,我有:

from .apply_preprocessing import *
from .convertion import *

sources/preprocessing/apply_preprocessing 我有:

from Sources.Preparation.Features.get_qualified_edges import get_all_GeneDisease_unweighted_disease2disease_qualified_edges
from Sources.Preparation.Features.get_qualified_edges import get_GPSim_disease2disease_qualified_edgesjk

在目录source/preparation/features/get_qualified_edges.py:

from Sources.Preprocessing.convertion import Converter # added this lien causes error to be raised
from itertools import combinations

Sources/preprocessing/conversion.py 我没有导入任何东西。

以下是由于出现错误而运行的文件序列:

sources\__init__.py
sources\preparation\__init__.py
sources\prepartion\features\__init__.py
sources\preparation\features\build_features.py
sources\preparation\features\get_qualified_edgdes.py
sources\preprocessing\__init__.py
sources\preprocessing\apply_preprocessing.py
\\error raise

当我从Sources.Preprocessing.convertion 导入一个类时引发错误,如下所示。在source/preparation/features/get_qualified_edges.py:

from Sources.Preprocessing.convertion import Converter # added this lien causes error to be raised

如果你们需要有关此问题的更多信息,请告诉我。

我想知道的是:为什么会出现这个问题? 当我将ConverterSources.Preprocessing.convertion 移动到Sources.Preparation.Data.conversion 时,我解决了这个问题。

观察

我观察到的是,当Sources.Preprocessing.modules_A(在Sources.Preparation.modules_C 中导入)和Sources.Preparation.modules_B(在Sources.Preprocessing.modules_D 中导入)之间没有“交叉”导入时,错误消失了。

就是这样。模块之间没有直接的“交叉”导入,而是在父模块之间存在“交叉”导入,如果这有意义的话。

【问题讨论】:

  • 您的导入结构很复杂,因此很难确定,但我怀疑您有模块 A 导入 B,而 B(直接或间接)导入 A。A 定义了 B 需要的函数 它的import B 声明之后。 Python 中的导入是可执行语句,因此解释器在被告知导入 B 时会暂停处理 A。这可能意味着在导入 B 时尚未处理 A 中所需的 def

标签: python class import module


【解决方案1】:

问题在于您正在从文件中引入循环导入。

对于sources/preprocessing 中的文件,您正在从source/preparation 导入内容。但反过来,这些文件会从source/preprocessing 导入内容。

一旦你有了类似于

的导入链

A.py -> B.py -> C.py -> B.py -> E.py

(直接循环)

A.py -> B.py -> C.py -> D.py-> B.py -> E.py

(间接循环)

那么它将无法继续导入模块,因为它不可能终止。

在 python 中解决这个问题的一个简单方法是使用本地导入。

例如,而不是

from Sources.Preprocessing.convertion import Converter 
# more code.....

class A:

  def foo():
    bar = Converter()

您可以改为使用本地导入,例如

# more code.....

class A:

  def foo():
    from Sources.Preprocessing.convertion import Converter 

    bar = Converter()

这样它只会在您实际使用该对象之前导入。这将避免一开始就导入所有内容,从而避免循环导入。


编辑:

简而言之,回答 OP 关于这个特定问题的问题:

您在代码中某处启动了 preprocessing 模块的导入。 (可能在sources\preparation\features\get_qualified_edgdes.py?不太确定) 此时,preprocessing 被添加到 sys.modules 命名空间,但作为一个空模块(占位符)。

稍后在同一个导入链中,在文件source/preparation/features/get_qualified_edges.py 中,行

from Sources.Preprocessing.convertion import Converter

尝试从Preprocessing模块导入convertion,但它会找到一个空模块(因为它仍在导入它的过程中)因此找不到对应的名称(convertion在这种情况下)。

【讨论】:

  • 我理解你的意思,但这如何适用于我的情况?查看以这种方式添加时导致错误的行from Sources.Preprocessing.convertion import Converterconversion.py 不会导入任何内容。因此,就我而言,没有您所说的任何直接或间接循环。导入刚刚在 convert.py 结束。我相信我的问题需要稍微不同的解决方案。
  • 我认为来自preprocessing/apply_preprocessing.pyfrom Sources.Preparation.Features.get_qualified_edges import ... 是您的导入问题的主要原因。查看片段,preparation/features/__Init__.pyfrom .get_qualified_edges import * 最终创建了一个导入链,导致 preprocessing/apply_preprocessingfrom Sources.Preparation.Features.get_qualified_edges import ...
  • 您应该重构 preparation\features\get_qualified_edgdes.py 或使用建议的本地导入方法。至于它只使用附加的from Sources.Preprocessing.convertion import Converter 抛出错误的原因,这是因为现代python 将允许循环导入,当它发生时它会指向一个空模块。但是在该模块的导入过程中,如果您引用其中的函数或类,它会看到它是一个空模块(因为它还没有完成导入)并抛出 ImportError 的异常,即找不到引用的名称。
  • 你能展示一下我创建的导入链是什么样的吗?我只是不明白为什么在我的案例中存在循环导入,因为所有导入的文件(init.py 除外)都直接导入其他文件。我可以看到同一个文件被导入两次,但没有循环导入。请给我看看它的样子。
  • 您必须包含更多文件内容,因为您当前的描述不充分,链中的某些文件丢失了。
猜你喜欢
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多