2

要するに、Python では、同じモジュールの複数のインスタンスを作成するのは非常に簡単で、各インスタンスには独自のグローバル変数のセットがあります。

このような複数のインスタンス化を検出して例外を発生させるには、モジュールにチェックを追加する必要があります。

私の問題はこれと同じです: モジュールが複数回インポートされました

これは、問題を再現するための最小のディレクトリ構造です。

/test/a/__init__.py

/test/a/aa.py:
print "aa: __name__: ", __name__

/test/b/b.py:
from a import aa
import aa

それで

export PYTHONPATH=/test:/test/a
python /test/b/b.py

プリント:

aa: __name__:  a.aa
aa: __name__:  aa

そのため、モジュール aa.py が異なる名前で 2 回インポートされました。

言うまでもなく、モジュール aa.py は 2 セットのグローバル変数を取得するため、このモジュール内のすべてのロジックが台無しになります。

もちろん、上記の些細な例では、目でエラーを検出するのは簡単ですが、複数のサブディレクトリを持つ複雑なプロジェクトでは、これらのエラーが定期的に発生し続けます。

したがって、本当にグローバルな変数やプロセス全体のストアなどが必要です。何か案が?

編集: Bibhas は、同じグローバル変数の複数のインスタンスの例を求めました。ここにあります:

/test/a/__init__.py

/test/a/aa.py:
print "aa: __name__: ", __name__

import thread
import time

test_var = __name__

def test():
    for i in range(0,5):
        print "aa thread: test_var: ", test_var
        time.sleep(1)

thread.start_new_thread( test, () )

/test/b/b.py:

print "b: __name__: ", __name__

from a import aa
import aa

import time
time.sleep(10)

現在実行中

export PYTHONPATH=/test:/test/a
python /test/b/b.py

プリント:

aa: __name__:  a.aa
aa: __name__:  aa
aa thread: test_var:  aa
aa thread: test_var:  a.aa
aa thread: test_var:  aa
aa thread: test_var:  a.aa
...

したがって、変数 test_var の 2 つのインスタンスがあることは明らかです。このモジュールにシングルトンを実装しようとすると、このシングルトンのインスタンスが 2 つになります。

Edit2:したがって、Guy Lが提案するソリューションは次のようなものです:

/test/a/aa.py:
import os
if "aa.py" in os.environ:
    raise Exception("Duplicate instantiation of aa.py")
os.environ["aa.py"] = __name__

問題なく動作するようです (複数のスレッドで import を呼び出さない限り)。誰かがより良いものを持っていますか?

4

2 に答える 2

2

これは醜い回避策ですが、 os.environ[] を使用して環境変数を設定できます。環境変数を汚染するので、あまり好きではありません。

これらを設定する方法は次のとおりです。 http://code.activestate.com/recipes/159462-how-to-set-environment-variables/

がんばれ、ガイ

于 2013-05-10T07:09:22.763 に答える
0

問題は、パス内の 2 つの異なるエントリからモジュールを利用できるようにしていることです。

プロジェクトディレクトリ全体をパスに含める必要があり、プロジェクト内の場所に関係なく実行されるすべてのモジュールのインポートは、インポートにフルパスを使用するため、例の代わりに次のようにする必要があります。

export PYTHONPATH=/test
python /test/b/b.py

また、b.py の最初の行のように、常にインポートを使用する必要があります。

from a import aa
于 2015-12-23T15:04:04.793 に答える