-3

さて、タイトルが言うように、私はインポートのグループを取得し、すべてがクラスをインポートし、すべてそれを実行するスクリプトと同じフォルダーにあります。

from lvl import lvl
from get import get
from image import image
from video import vid
from video import MLStripper
from system import system
from setting import setting
from listsearch import lists

python3にはreload iircは無いけどimp.reload()はあるけど動かないようで、

モジュールではないというエラーをスローするだけです(クラスなので機能しません)

インポートされたクラスを少し編集するたびに、スクリプトを再起動する必要があります

imp.reload() が機能するように、スクリプトを開始したり、ほとんどのスクリプトを書き直したりすることなく、クラスをリロード/再インポートして編集の効果を表示する方法はありませんか?

python3、linux(ただし、ウィンドウでも動作する場合は好ましい)

編集1:

例:私が使用する場合:

import system
system.system.temp()

戻ります:

65°C

°Fを表示するように変更し、imp.reloadを使用してリロードすると

imp.reload(system)
system.system.temp()

戻ります:

149°F

だから、それは動作しますが、私が使用する場合

import system as _system
from system import system
system.temp()

戻ります:

65°C

次に、°Fを表示するように変更し、imp.reloadを使用してリロードします

imp.reload(_system)
from system import system
system.temp()

それはまだ戻ってくる

65°C

しかし、もう一度、このように呼び出すと:

_system.system.temp()

戻る

149°F

idk なぜそれが原因ですが、それは while ループで発生するのですか?

編集2:

ファイル名: system.py:

テスト用に変更する前に:

class system:
  def temp():
    temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
    temperature = temperature[:2]
    return(temperature+"°C")

テスト用に変更した後:

class system:
  def temp():
    temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
    temperature = temperature[:2]
    temperature = str(9.0 / 5.0 * int(temperature) + 32).split(".")[0]
    return(temperature+"°C")
4

2 に答える 2

3

reloadモジュールのみが可能です:

引数はモジュール オブジェクトである必要があるため、以前に正常にインポートされている必要があります。

あなたの場合、モジュール オブジェクトへの参照はありません。import後で呼び出すためだけに、他の目的で使用したくない場合でも、それを使用する必要がありますreload

また、 の後にreloadimport名前を変更します。

古いオブジェクトへの他の参照 (モジュールの外部の名前など) は、新しいオブジェクトを参照するために再バインドされないため、必要に応じて、それらが発生する各名前空間で更新する必要があります。

するとfrom foo import bar、それbarは「モジュールの外部の名前」になるため、明示的に再バインドする必要があります。

考えてみれば、このように機能しなければなりません。reload定義がモジュールの以前のバージョンに依存しているすべてのオブジェクトを列挙して、それらを更新する方法はありません。できたとしても、無限のサイクルが存在する可能性があります。また、古いバージョンにあったクラスの定義さえも新しいバージョンになかったらどうなるでしょうか? または、クラスが動的に定義された場合は?

別の見方をすると、from foo import barに非常に似ていimport foo; bar = foo.barます。barの名前空間ではなく、あなたfooの名前空間の名前なので、reload(foo)触れません。foo.bar新しいものをもう一度コピーする必要があります。

これらの問題をすべて解決する簡単な方法は、.from foo import barの後にすべての行を繰り返すことreloadです。


単純なケースの場合:

import video
from video import MLStripper

# ... later

imp.reload(video)
from video import MLStripper

ただし、ほとんどの例には明らかな名前の競合がありfrom video import videoますreload(video)videoそのため、モジュール オブジェクトへの別の参照が必要です。

Python は、あなたが使用できるものを保持しています:

imp.reload(sys.modules['video'])
from video import MLStripper

または、as句または=代入を使用して、任意の名前を付けることができます。

import video as _video
from video import video

# ... later

imp.reload(_video)
from video import video

あなたのコメントと編集した質問から、さらに問題があるようです。単純な衝突しないケースの 1 つを使用して、それについて説明しましょう。

あなたは実際に次のようなことをしていると思います:

import video
from video import MLStripper

stripper = MLStripper('foo")

# ... later

imp.reload(video)
from video import MLStripper

最初の行でモジュールが正常にリロードされvideo、2 行目でそのMLStripperクラスがグローバルにコピーされるため、MLStripper作成した新しいインスタンスはすべて新しいタイプになります。

MLStripperしかし、それは既存のインスタンスには影響しませんstripper

と同じようMLStripperに、stripper「モジュールの外部の名前」の 1 つです。しかし、実際にはさらに悪いです。それを調整するにreloadは、コードの新しいバージョンが作成された時点から有効であった場合、その状態がどうなるかを把握する必要があります。これが解決不可能な問題であることは明らかです。


パッチを適用したいインスタンスがわかっている場合は、クラスを処理したのと同じ方法でそれらを効果的に処理できます。それらを再度作成するだけです。

imp.reload(video)
from video import MLStripper
stripper = MLStripper('foo")

それでも十分でない場合は、次の 3 つのハックの可能性があります。

  • メソッド、属性などをインスタンスとそのインスタンスにモンキーパッチします__class__
  • インスタンスの__class__属性に直接パッチを適用して、クラスから継承されたものはすべて新しいクラスから継承されるようにします。
  • pickleの前にインスタンスをreloadシリアル化し、後で逆シリアル化します。

非常に単純なケースでは、これら 3 つすべてが機能します。より複雑なケースでは、何をしているのかを理解する必要があります。


このようなものの多くを関数にまとめることができますが、ローカルとグローバルがどのように機能するか (およびインポートとリロードがどのように機能するか) を理解する必要があることに注意してください。そうしないと、混乱することになります。

より簡単な解決策は、「すべての状態をダンプする」関数と「すべての状態をロードする」関数を作成することです。その後、すべてをダンプし、終了し、再起動して復元できます。reloadPython のチュートリアルと ipython のドキュメントの両方で、 ;を使用する代わりにこれを行ういくつかの異なる方法について説明しています。おそらく戻ってそれらを読み直す価値があります。

于 2013-06-18T21:22:36.430 に答える
2

からモジュールにアクセスし、それsys.modulesをリロードしてから、インポートした名前を再割り当てします。

imp.reload(sys.modules['lvl'])
from lvl import lvl

imp.reload(sys.modules['get'])
from get import get

すべてのfrom something import name構文は、インポートしてから、参照先の同じオブジェクトsomethingにバインドするだけです。namesomething.name

を使用sys.modulesすると、モジュールを再度明示的にインポートする必要がなくなり、リロード後に再バインドするオブジェクトの新しい定義に到達できます。

于 2013-06-18T21:18:23.947 に答える