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

そして、はい、Geneticにありsys.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、2回目に実行することはありません。代わりに、すでにメモリにあるものをsettingsロードするだけGAです(インポートを実行しているため、現在ほとんど空です)。

したがって、探しているものがまだ定義されていないため、そのsettings中のものは失敗から使用しようとします(の処理がまだインポートを通過していないため)。GAGAGA.py

これにより、例外の発生の評価がsettings.py行われます。これは、インポートの失敗として現れます(インポート中に発生した例外により、インポートが失敗するため)。

ソリューション

a)そもそも状況を避けてください。

一般に、そもそも循環インポートを避けるように努める必要があります。多くの場合、後でデバッグするのが難しい、本当に奇妙な依存関係構造があることを意味します。

これを行う1つの方法は、両方のモジュールで必要なものを見つけて、他の2つのモジュール間で共有できる別の3番目のモジュールに分割することです。したがって、BでAxを使用し、AでByを使用する代わりに、 AとBの両方でCxとCyを使用します。

b)すべてがロードされるまで、循環インポートからのものを実際に使用しようとしないでください。

もう1つできることは、すべてのインポートが完了するまで、別のモジュールからの使用を延期することです。つまり、インポートされたモジュールの内容をトップレベルのコードから参照しようとせずに、すべてのインポートが完了したら、クラス初期化子または後で呼び出すことができる関数に配置します。

たとえば、これの代わりに...

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 に答える