web-dev-qa-db-ja.com

Python: 'from X import Y'でインポートされたコンポーネントYをリロードしますか?

Pythonでは、import X_を使用してインタープリターセッションでモジュールXをインポートし、外部でモジュールが変更されたら、reload(X)を使用してモジュールをリロードできます。その後、変更はインタプリタセッションで利用可能になります。

_from X import Y_を使用してモジュールXからコンポーネントYをインポートするときにこれも可能かどうか疑問に思っています。

Yはモジュール自体ではなく、モジュール内のコンポーネント(この場合はクラス)のみであるため、ステートメント_reload Y_は機能しません。

インタプリタセッションを終了することなく(またはモジュール全体をインポートせずに)モジュールの個々のコンポーネントをリロードすることはまったく可能ですか?

編集:

明確にするために、問題はクラスまたは関数YモジュールXからインポートし、パッケージXからモジュールYではなく、変更時にリロードすることです。

76
cschol

Yがモジュール(およびXがパッケージ)の場合、reload(Y)は問題ありません。それ以外の場合は、良いPythonスタイルガイド(私の雇用主など)が言う理由がわかります。 to never何でもインポートexceptモジュール(これは多くの大きな理由の1つです-それでも、私はそれがいくら説明しても、関数とクラスを直接インポートし続けるnot良いアイデア;-)。

48
Alex Martelli

回答

私のテストから。単純なreload(X)を示唆するマークされた回答は機能しません。

私が正しい答えを伝えることができるものから:

# python3.x would require
# from importlib import reload
import X
reload( X )
from X import Y

テスト

私のテストは次のとおりでした(Python 2.6.5 + bpython 0.9.5.2)

X.py:

def Y():
    print "Test 1"

bpython:

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after
81
Catskul

まず、リロードを回避できる場合は、リロードを使用しないでください。しかし、理由があると仮定しましょう(つまり、IDLE内でのデバッグ)。

ライブラリをリロードしても、モジュールの名前空間に名前が戻されません。これを行うには、変数を再割り当てします。

f = open('Zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()

from Zoo import snakes
print snakes

f = open('Zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()

import Zoo
reload(Zoo)
snakes = Zoo.snakes # the variable 'snakes' is now reloaded

print snakes

他のいくつかの方法でこれを行うことができます。ローカルの名前空間を検索し、問題のモジュールからのものを再割り当てすることでプロセスを自動化できますが、私たちは十分に邪悪だと思います。

7
wisty
from modulename import func

import sys
reload(sys.modules['modulename'])
from modulename import func
7
mirek

これを行いたい場合:

from mymodule import myobject

代わりにこれを行います:

import mymodule
myobject=mymodule.myobject

これで、計画と同じ方法でmyobjectを使用できます(どこでも面倒で読みにくいmymodule参照なし)。

インタラクティブに作業していて、mymoduleからmyobjectをリロードする場合は、次を使用できます。

reload(mymodule)
myobject=mymodule.myobject
4
Chris Fryer

from X import Y、次の2つのオプションがあります。

reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module

または

Y=reload(sys.modules['X']).Y

いくつかの考慮事項:

A.インポートスコープがモジュール全体ではない場合(例:関数のインポート)-2番目のバージョンを使用する必要があります。

B. Yが別のモジュール(Z)からXにインポートされる場合-Zをリロードする前に、Xをリロードし、モジュールをリロードするよりも、すべてのモジュールをリロードする(例:[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]を使用) Yの値を更新しません。

2
Ohad Cohen
  1. reload()モジュールX
  2. YからXをインポートするreload()モジュール。

再読み込みしても、他の名前空間にバインドされている既に作成されたオブジェクトは変更されないことに注意してください(Alexのスタイルガイドに従っても)。

1
Denis Otkidach

Jupyter環境で作業していて、すでにfrom module import functionは、マジック関数autoreloadを使用できます。

%load_ext autoreload
%autoreload
from module import function

IPythonでのautoreloadの紹介は here で与えられています。

0
Yanqi Huang