9

たくさんの変数を持つPythonモジュールがあります。これらの変数は、他の多くのモジュールによって使用および変更されます。そして、このモジュールが発生したときに(更新のために)それ自体からこのモジュールをリロードしたいと思います。

どうやってするか?

upd:そう..これは私、質問の作者、質問の公開日から8年後です。なぜそのようなことをしようとするのか、私にはまったくわかりません。

これを読んだ場合は、代わりに適切な構成管理手法(ほとんどの場合フレームワークによって提供される)を使用してみてください。

# ==================================
# foo.py

spam = 100

def set_spam(value):
    spam = value
    foo = reload(foo) # reload module from itself

# ==================================
# bar.py

import foo
print foo.spam # I expect 100
# assume that value changes here from some another modules (for example, from eggs.py, apple.py and fruit.py)
foo.set_spam(200)
print foo.spam # I expect 200
4

7 に答える 7

3

自分のように見えない自己変更コードシステムを意図的に設定しない限り、達成しようとしていることには多くの問題があります。

1.グローバル変数

spam = 100

def set_spam(value):
    spam = value
    foo = reload(foo) #reload module from itself

これは機能しません。Pythonクロージャがどのように機能するかにより、行は関数内にspam = value新しいローカル変数を作成しますが、これは使用されません。グローバルの値を適切に変更するには、次のようにキーワードを使用する必要があります。spamset_spamspamglobal

spam = 100

def set_spam(value):
    global spam
    spam = value

2.「自分自身から」モジュールをリロードする

私の知る限り、これを実際に行う方法はありませんし、そうする必要もありません。import-edしたモジュールは、他のモジュールからから呼び出されます__main__。その呼び出し元のモジュールから更新するだけです。はい、モジュールの自己インポートを試みることはできますが(mgilsonが言及しているように、無限ループの問題が発生する可能性があります)、それでも( "foo"という名前の例を使用して)、モジュール自体をインポートする場合は、を持っていてfoo.foofoo.reload(foo)(それが有効な場合でも)のようなことを行うとfoo、ベースではなくサブをリロードするだけです。

3.まったくリロードfoo.pyします

# ==================================
# foo.py

spam = 100

def set_spam(value):
    global spam
    spam = value

このコードの先頭で、に100を割り当てていることに注意してくださいspamモジュールをインポートするたびに、それを再度実行します。したがって、spamインポートされたコードでの値をすでに変更している場合でもfoo、モジュールをリロードすると、実際に行った変更は破棄されます。例:

>>> import foo
>>> foo.spam
100
>>> foo.spam = 9
>>> foo.spam
9
>>> reload(foo)
>>> foo.spam
100

したがって、変数に加えた変更をで保持したい場合は、モジュールをリロードしないfooでください。さらに、変更するために関数を使用する必要もありません。私が行ったように、直接設定するだけです。set_spamspam

4.この「変更された」モジュール値を他のモジュールで使用しようとしています

最後に、あなたがやろうとしていることを私が正しく理解していれば、それはうまくいきません。これは主に、パート3で述べたことが原因です。ロードするたびfooに、spam=100行はの値をリセットしますspamfoo同様に、モジュールを他の2つの異なるモジュールにインポートする場合、それぞれがモジュールをインポートするとspam = 100、他のモジュールが行うこととは完全に独立して、それぞれがで始まりますfoo.spam。たとえば、両方bar1.pyに次bar2.pyの行が含まれている場合import foo

>>> import bar1, bar2
>>> bar1.foo.spam
100
>>> bar2.foo.spam
100
>>> bar1.foo.spam = 200
>>> bar1.foo.spam
200
>>> bar2.foo.spam
100

あなたがやろうとしていることについてのより多くの説明があれば、コードをより良く機能させるためにコードを再構築するのを手伝うことができます。

于 2012-12-10T17:02:02.203 に答える
2

Python2.6.2では簡単です。モジュールの名前が「t」で、次のように定義されているとします。

import imp

def reload():
    name="t"
    imp.load_module(name,*imp.find_module(name))

print("loaded")

このモジュールをロードした後、別のメンバーを追加してt.reload()を実行します。

ps誰もがこれは悪い考えだと思っていると思います。おそらく正しいのですが、モジュールをインタラクティブに開発している場合は、物事がより便利になるかもしれません。コードを他の人に配布する前にそれを取り出してください。そうしないと、他の人が混乱する可能性があります。

于 2013-05-26T18:25:07.133 に答える
2

ここ

import sys

reload(sys.modules[__name__])

注意:これはモジュールでは機能しませんmainが、他のモジュールでは機能します。

于 2018-03-31T01:18:53.907 に答える
1

無限ループに巻き込まれずにこれをきれいに行う方法がわかりません。resetたぶん、関数を持っている方が良いでしょうか?

def reset():
    global spam
    spam = 100

このデザインはまだ私には少しファンキーに見えることに注意してください。より良いデータカプセル化は、おそらく長期的には大いに役立つようです-おそらく次のようなものです:

def new_namespace():
    return {'spam':100}

そうすれば、他の各関数は、名前空間に依存するのではなく、名前空間ディクショナリを引数として受け入れることができfooます。

于 2012-12-10T16:32:40.410 に答える
1

モジュールがリロードされた回数を数えることもできます!:

mymodule.py

import importlib
import sys

count = 0
var = 0

def refresh():
    global count
    c = count
    importlib.reload(sys.modules[__name__])
    count = c + 1
    print (f'reloaded {count} time(s)')

main.py

import mymodule

mymodule.var = 'changed'
mymodule.refresh()
  # -> reloaded 1 times(s)
print(mymodule.var)
  # -> 0
mymodule.refresh()
  # -> reloaded 2 times(s)
于 2020-04-22T23:15:19.987 に答える
0

この操作はまったく意味がありません。Pythonドキュメントから:

reload(module):以前にインポートされたモジュールをリロードします。引数はモジュールオブジェクトである必要があるため、以前に正常にインポートされている必要があります。

したがって、以前reloadに実行した他のモジュールのコンテキストからのみセンスを作成しますimport

于 2012-12-10T16:40:14.697 に答える
0

これは前の回答の別のバージョンで、カウンターが存在しない場合にのみ初期化されます。Python3.8.6でテスト済み

# mod.py
import importlib, sys

a=0

def reload():
  
    importlib.reload(sys.modules[__name__])
    global i
    try:
        i += 1
    except:
        i = 1
    print(f'reloaded {i} time(s)')

# main.py
import mod

mod.a = 10
print (mod.a) # -> 10
mod.reload() # -> reloaded 1 time
print (mod.a) # -> 0
mod.reload() # -> reloaded 2 times
于 2021-04-28T23:23:57.343 に答える