2016-09-26 8 views
1

私はPython 3.5で書かれたプログラムの一部を持っており、最初の2つのモジュールをテストすることから始めました。モジュールの1つで、2つのグローバル変数が理解できない理由で元の値に戻っているように見える問題を切り分けることができました。これらのグローバル変数の1つ(event_count)は、単一の関数(grepは文字列 "event_count"がmy * .pyファイルのどこにも現れないことを示します)でのみ使用されますが、変数の値は関数。このモジュールの他のグローバル変数のprintステートメントを追加すると、同時にその元の値に戻ります。 event_countを別のモジュールに移動すると、sensorlogic.event_counteventcount()になり、初期化を他のモジュールに移動すると動作が終了するため、修正済みですがわかりません。ここでPythonモジュールのグローバル変数は自動的にリセットされます

はモジュールsensorevalで、event_countを使用するすべてのコードです:

event_count = 0 

def eventcount(increment): 
    global event_count 
    print("entering eventcount, increment =", increment, 
      ", event_count =", event_count) 
    event_count += increment 
    print("leaving eventcount, event_count =", event_count) 
    return event_count 

私は次のコードセグメント実行した場合:

e.setvalue(1) 
    print("I am at marker #1") 
    eventcount(0) 

を(e.setvalue()の最後のアクションがへの呼び出しでありますeventcount(0))この出力を生成します:

entering eventcount, increment = 0 , event_count = 4 
leaving eventcount, event_count = 4 
I am at marker #1 
entering eventcount, increment = 0 , event_count = 0 
leaving eventcount, event_count = 0 

私は2つのモジュールを妥当なサイズにトリミングしようとしましたが、そうしても問題は解決しません。私はそれに取り組んでいきます。以前はPython 3を使ったことがなく、ちょっとしたPython 2.7の経験しかなかったので、私は何か愚かなことをしていると思っています。何も分かりません。

私の例は、変数event_countがグローバルであるだけで静的になるという点で指摘されているいくつかの関連記事とは異なると私は信じています。この単一の関数でのみ使用されます。文字列 "event_count"は、このモジュールまたは他のモジュールのどこにも表示されません。


多くの編集/再実行の繰り返しの後で、私は何が起こっているかを実証する非常に小さな例があります。これには、合計8行のコードを持つ2つのモジュールが含まれます。第一のモジュール、a.py__main__である:

import b 
c = 0 
if __name__ == '__main__': 
    b.init() 
    print("c =", c) 

第二モジュールがb.pyある:a.py実行

import a 
def init(): 
    a.c = 1 

は出力を生成します

c = 0 

Iはcはまだから1であることが期待しましたa.c = 1b.pyです。私はどちらか、それを説明することはできませんが、それが関連していると思わ

Traceback (most recent call last): 
    File "...\a.py", line 1, in <module> 
    import b 
    File "...\b.py", line 1, in <module> 
    import a 
    File "...\a.py", line 3, in <module> 
    b.init() 
AttributeError: module 'b' has no attribute 'init' 

はまた、私はa.pyからif __name__ == '__main__'を削除することによって、このさらなるを削減しようとしていないが、その後の例では、もはや実行されます。


私は次のコードが何が起こっているのかを示していると信じています。 3つのモジュールが含まれています。a.py

print("__name__ =", __name__) 
import b 
print("__name__ =", __name__) 
def f(): pass 
print(f) 
if __name__ == '__main__': 
    print("f is b.a.f?", f is b.a.f) 

b.py

import a 

c.py

import a 
import b 
print("__name__ =", __name__) 
print("a.f is b.a.f?", a.f is b.a.f) 

あなたは結果を与え、a.pyを実行することによって、問題を見ることができます:

__name__ = __main__ 
__name__ = a 
__name__ = a 
<function f at 0x0000021A4A947840> 
__name__ = __main__ 
<function f at 0x0000021A484E0400> 
f is b.a.f? False 
インポートサイクルの結果の一部ではないように、

c.pyを実行中:

__name__ = a 
__name__ = a 
<function f at 0x000001EA101B7840> 
__name__ = __main__ 
a.f is b.a.f? True 
+0

[グローバル変数を作成した関数以外の関数でグローバル変数を使用する]の可能な複製(http://stackoverflow.com/questions/423379/using-global-variables-in-a-function-other-than-作成したもの) – rll

+0

これは関連しています:http://stackoverflow.com/q/3536620/4996248 –

+0

問題が消えてしまうように調整することが何であれ、手がかりが必要です。また奇妙なことに、あなたの出力には 'event_count'が実際にはインクリメントされていないと表示されます。 –

答えて

1

のは、ステップバイステップであなたの2モジュールの例を見てみましょう。その動作は期待されていますが、最初は混乱し、おそらく他のケースでは何が起こっているのかがよく分かります。

スクリプトとしてaを実行する場合、それはsys.modulesaとしてではなく、__main__としてインポートされません。最初のステートメントはimport bです。空のモジュールオブジェクトsys.modules['b']が作成され、初期化が開始されます。

bの最初の行は、aを再度インポートします。通常、sys.modules['a']の下にあるモジュールオブジェクトが見つかりますが、この場合はaをスクリプトとして実行しているため、最初のインポートが別の名前で行われています。今度はaの名前がaであり、今度は__main__ではないので、a.cはゼロに設定され、それ以外は何も起こりません。

実行がbに戻ります。 sys.modules['a'].cに1を設定する関数initを作成します。 aモジュールへの参照は非常に明示的に書かれています。これが矛盾の根本原因です。

bをインポートすると、実行はaに戻りますが、sys.modules['a']に戻りません。次の行、c = 0は実際にはsys.modules['__main__'].cをゼロに設定します。うまくいけば、この時点で問題を見ることができます。次の行はb.initを呼び出し、sys.modules['a']を1に設定します。次に、期待どおりに0であるsys.modules['__main__']を印刷します。あなたが1を取得します

は、この博覧会の正しさを確認するには、print文に

print(sys.modules['a'].c) 

を追加してみてください。また、sys.modules['a'] is sys.modules['__main__']Falseになります。これを回避する最も簡単な方法は、特定のモジュールのインポートで他のモジュールのメンバーを初期化することではありません。

具体的なケースについては、http://effbot.org/zone/import-confusion.htm#using-modules-as-scriptsに記載されています。

その他のリソース

あなたがここにインポート・システムの砂のような内容に、より多くの情報を得ることができます:https://docs.python.org/3/reference/import.html。さまざまなトラップと輸入品の警告がここに記載されています:http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html

関連する問題