モジュールをアンロード(再ロード)するにはどうすればよいですか?


797

実行時間の長いPythonサーバーがあり、サーバーを再起動せずにサービスをアップグレードできるようにしたいと考えています。これを行う最良の方法は何ですか?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()

53
メモ:「インポート」は「ロード」を意味するのではなく、「ロードされていない場合はロードしてからネームスペースにインポートする」ことを意味します。
Kos

3
「アンロード」はpythonではまだ不可能なので、質問には「アンロード」を含めないでください。ただし、リロードは以下で回答する既知のパラダイムです
robertmoggach

py2exeアプリで動的モジュールを使用すると、同じ問題が発生しました。py2exeは常にzipディレクトリにバイトコードを保持するため、リロードは機能しませんでした。しかし、私はimport_fileモジュールを使用した実用的なソリューションを見つけました。現在、私のアプリケーションは正常に動作しています。
Pritam Pan 2016

2
.pycファイルを削除しようとしてコードが使用しているために「アンロード」したい場合はどうなりますか?
darkgaze

回答:


792

reload組み込み関数(Python 3.4以降のみ)を使用して、すでにインポートされているモジュールをリロードできます。

from importlib import reload  
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

Python 3ではreloadimpモジュールに移動されました。3.4、impを支持して非難しimportlib、そしてreload後者に添加しました。3以降をターゲットとする場合は、呼び出し時に適切なモジュールを参照するreloadか、インポートします。

これがあなたの望んでいることだと思います。Djangoの開発サーバーなどのWebサーバーはこれを使用しているため、サーバープロセス自体を再起動せずにコード変更の影響を確認できます。

ドキュメントから引用するには:

Pythonモジュールのコードが再コンパイルされ、モジュールレベルのコードが再実行されて、モジュールのディクショナリの名前にバインドされる新しいオブジェクトのセットが定義されます。拡張モジュールのinit関数は、2回目は呼び出されません。Pythonの他のすべてのオブジェクトと同様に、古いオブジェクトは、参照カウントがゼロになって初めて回収されます。モジュール名前空間の名前は、新しいオブジェクトまたは変更されたオブジェクトを指すように更新されます。古いオブジェクトへのその他の参照(モジュールの外部の名前など)は、新しいオブジェクトを参照するために再バインドされず、必要に応じて、それらが発生する各ネームスペースで更新する必要があります。

質問で述べたFooように、Fooクラスがfooモジュール内にある場合は、オブジェクトを再構築する必要があります。


10
実際、django devサーバーは、ファイルを変更すると自動的に再起動します..(モジュールをリロードするだけでなく、サーバーを再起動します)
hasen

25
この「is_changed」関数はどこから来たのですか?私はそれに関するドキュメンテーションを見ません、そしてそれは私のPython 3.1.3環境で実行されません、そしてそれは2.6.4で実行されません。
jedmao

5
馬鹿げたことなく、Djangoはreloadを使用することはできません:pyunit.sourceforge.net/notes/reloading.html
raylu

14
@BartoszKP Xがモジュールでない場合は、次のことができますimport sys; reload(sys.modules[X.__module__])
drevicko

5
@jedmao @JamesDraper私はis_changed関数があなたが書かなければならないだろう任意の関数だとかなり確信しています。組み込みではありません。たとえば、インポートするモジュールに対応するファイルを開き、キャッシュされたバージョンと比較して、変更されているかどうかを確認することができます。
James Mchugh、2018

252

Python 3.0–3.3では、以下を使用します。 imp.reload(module)

BDFLは答えこの質問を。

ただし、imp3.4で非推奨となり、importlib@ Stefanに感謝

私はと思うので、あなたが今使用すると思い、importlib.reload(module)私はわからないが、。


23
熱心な初心者は、Python 2と3の間の重要なニュアンスについて学ぶことに感謝しています
Smandoli

24
imp.reload(imp)は有効ですか?
ロイック・フォーレ-ラクロワ

2
@LoïcFaure-Lacroixはreload(__builtins__)2.x でも同じです
JBernardo

1
@Tarrasch:問題の例のように、リロードしたいPythonモジュールです。
ポールD.ウェイト2013

3
@LoïcFaure-Lacroixはい、インプはリロードできます。
Devyn Collier Johnson 2013

92

純粋なPythonでないモジュールを削除することは特に困難です。

:ここからいくつかの情報である、私は本当にインポートされたモジュールを削除するにはどうすればよいですか?

sys.getrefcount()を使用して、実際の参照数を確認できます。

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

3より大きい数値は、モジュールを取り除くのが難しいことを示します。自作の「空」(何も含まない)モジュールは、後にガベージコレクションされます。

>>> del sys.modules["empty"]
>>> del empty

3番目の参照はgetrefcount()関数のアーティファクトであるためです。


4
モジュールがパッケージの一部である場合、それもそこで削除する必要があることを発見しました:setattr(package, "empty", None)
u0b34a0f6ae

6
これは、特にネストされたモジュールを持つパッケージがある場合、正しい解決策です。reload()最上位のモジュールのみを再ロードします。最初にsys.modulesから削除しない限り、モジュール内のすべては再ロードされません。
Cerin

73

reload(module)、ただしそれが完全にスタンドアロンの場合のみ。他に何かがモジュール(またはモジュールに属するオブジェクト)への参照を持っている場合、古いコードが予想よりも長くぶらつくことによって引き起こされる、微妙で奇妙なエラーが発生します。isinstance、異なるバージョンの間で動作していません同じコード。

一方向の依存関係がある場合は、再ロードされたモジュールに依存するすべてのモジュールを再ロードして、古いコードへのすべての参照を取り除く必要があります。そして、再ロードされたモジュールに依存するモジュールを再帰的に再ロードします。

循環依存関係がある場合(パッケージのリロードを処理する場合など)は非常に一般的ですが、グループ内のすべてのモジュールを一度にアンロードする必要があります。reload()依存関係が更新される前に各モジュールを再インポートし、古い参照が新しいモジュールに侵入できるため、これを行うことはできません。

この場合、これを行う唯一の方法は、ハッキングsys.modulesすることです。sys.modules次のインポートでリロードしたい各エントリを調べて削除し、値が次のエントリも削除する必要がありますNone。また、失敗した相対インポートのキャッシュに関する実装の問題に対処。それはひどく良くありませんが、コードベースの外に参照を残さない完全に独立した依存関係のセットがある限り、それは実行可能です。

サーバーを再起動することをお勧めします。:-)


1
そのシナリオ専用のdreloadではありませんか?
Josh

@ジョシュ:いいえ、それはパッケージツリーをリロードするためのものであり、それでもパッケージが外部/循環依存関係を持たない場合にのみ機能します。
ボビンス

1
None私はこの問題に正確に直面しているので、パーツを値で詳しく説明できますか?sys.modulesインポートされた依存関係からアイテムを削除し、インポートした依存関係の一部を削除しますNone
シュラマー2013年

@shclamar:背景については、stackoverflow.com / questions / 1958417 /… (およびそこからのリンク)を参照してください。None「実際の」エントリが削除されたときに、エントリがインポートメカニズムを介してどのように戻ってきたのか(import.cコードを見ても)は私にはわかりません。2.7 でそれを実行させることはできません。将来的には、暗黙的な相対インポートがなくなったため、問題はなくなりました。それまでの間、None値を持つすべてのエントリを削除すると、問題が解決するようです。
ボビンス2013年

1
@Eliethesaiyan:reload関数のことですか?これは組み込みで、ライブラリをインポートする必要はありません。
ボビンス

63
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]

3
+1。私の目標は、Python内でノーズテストを実行することでした。モジュールをロードしていくつかの関数の名前を変更したnose.run()後、呼び出した後も古い名前が残りましたreload(my_module) %run my_module
Peter D

5
モジュールが独自のサブモジュールをインポートする場合、それらも削除する必要があるかもしれません。のようなもの[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
drevicko 2014年

モジュールをアンロードするとは思わない。Python 3.8の場合:import sys; import json; del sys.modules['json']; print(json.dumps([1]))jsonモジュールは、sys.modulesに含まれていなくても機能しています。
Seperman

60

Python 2の場合は、組み込み関数reload()を使用します。

reload(module)

Python 2および3.2–3.3の場合、impモジュールからreloadを使用します

import imp
imp.reload(module)

ただし、バージョン3.4以降ではimportlib imp が推奨されているため、以下を使用してください。

import importlib
importlib.reload(module)

または

from importlib import reload
reload(module)

2
これらのケースのいずれかを処理するには:(もちろん最初にfrom six import reload_module必要ですpip install six
Anentropic

@Anentropic:6つのパッケージの使用を推奨することは良いアドバイスですが、構文はfrom six.moves import reload_moduledoc
x0s

23

次のコードでは、Python 2/3との互換性を確保しています。

try:
    reload
except NameError:
    # Python 3
    from imp import reload

reload()両方のバージョンと同じように使用できるので、物事が簡単になります。


18

受け入れられた回答は、XからのインポートYのケースを処理しません。このコードは、それと標準のインポートの場合も処理します。

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

リロードの場合は、新しくリロードされたモジュールに格納されている値に最上位の名前を再割り当てし、それらを更新します。


問題に気づいたのは、globals()がこの関数を定義したモジュールを参照しているため、この関数を呼び出すモジュールとは異なるモジュールで定義した場合、機能しないということです。
Joseph Garvin 2014年

インタラクティブな場合は>>> from X import Y、再読み込みしてから>>> __import__('X', fromlist='Y')
ボブスタイン

@ BobStein-VisiBone、それを機能させる方法はありfromlist='*'ますか?
マイクC

@MikeCはわかりません。ところで、私はfromimportステートメントでのほとんどすべての使用をやめる傾向にあります。ただ、荒涼import <package>とコードで明示的にpackage.symbol。これが常に可能または望ましいとは限らないことを認識してください。(1つの例外は次のとおりです。将来のインポートprint_functionから。)
ボブスタイン

マイクC:私にとってうまくいくのは foo = reload(foo); from foo import *
ホタルブクロ

16

これはモジュールをリロードする最新の方法です:

from importlib import reload

3.5より古いバージョンのPythonをサポートしたい場合は、次のことを試してください。

from sys import version_info
if version_info[0] < 3:
    pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
    from imp import reload # Python 3.0 - 3.4 
else:
    from importlib import reload # Python 3.5+

これを使用するには、を実行しreload(MODULE)MODULEリロードするモジュールに置き換えます。

たとえばreload(math)mathモジュールをリロードします。


4
または単にfrom importlib import reload。その後、行うことができますreload(MODULE_NAME)。この機能は必要ありません。
pault

私はmodulereload(MODULE_NAME)、単に説明するだけでなくreload(MODULE_NAME)、他の機能と競合する可能性が低いと考えています。
Richie Bendall

@RichieBendall申し訳ありませんが、この答えは完全に間違っています。reload()関数は、モジュール名ではなく、モジュールオブジェクトを受け取ります...ドキュメントを読んでください:docs.python.org/3/library/importlib.html#importlib.reloadそして、@ paultに同意します-これは「modulereloadとして」余計なものです。
mbdevpl 2018

私はあなたの意見を反映するために私の答えを変更しました。
Richie Bendall

13

サーバーを使用していないが、開発中にモジュールを頻繁にリロードする必要がある場合は、ここにヒントがあります。

まず、Jupyter Notebookプロジェクトの優れたIPythonシェルを使用していることを確認します。Jupyterをインストールした後、あなたがそれを起動することができipython、またはjupyter consoleより良い、または、jupyter qtconsole起動できます。これにより、どのOSでもコード補完機能を備えた、色分けされた素敵なコンソールが得られます。

シェルで次のように入力します。

%load_ext autoreload
%autoreload 2

今、毎回スクリプトを実行するに、モジュールがリロードされます。

以外2にも、自動リロードマジックには他のオプションがあります

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.

7

私のようにすべてのモジュールをアンロードしたい場合(Emacsの下でPythonインタープリターで実行している場合):

   for mod in sys.modules.values():
      reload(mod)

詳細については、「Pythonモジュールの再読み込み」を参照してください。


実際には、それが確実に機能するようには見えません(2.6では)sys.modules.values()。次に例を示します。>>> type(sys.modules.values()[1])<class 'email.LazyImporter'>したがって、そのコードを実行しようとすると、コードはフォールオーバーします(実用的な解決策ではないことを知っています。指摘)。
フランシスデービー

書かれているように、それは初期のpythonでは動作しません。一部の名前を除外する必要がありました。そのコードを新しいコンピューターに移動したら、投稿を更新します。

2
:いくつかの変更後のPython 2.7で正常に動作しますif mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak

2
これは私にとってうまくいきます:import imp [ m .__ nameで " "でなく、imp.is_builtin(m .__ name__)ではないmの場合、sys.modules.values()でmのreload(m )]
Patrick Wolf

5

Enthought Traitsには、このためにかなりうまく機能するモジュールがあります。https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

変更されたモジュールをリロードし、それを使用している他のモジュールとインスタンス化されたオブジェクトを更新します。ほとんどの場合、__very_private__メソッドでは機能せず、クラスの継承を阻害する可能性がありますが、PyQtのGUIや、MayaやNukeなどのプログラム内で実行されるものを作成するときにホストアプリケーションを再起動する必要がなくなり、時間を大幅に節約できます。20-30%の確率では機能しませんが、それでも非常に役立ちます。

Enthoughtのパッケージは、ファイルが変更されたときにファイルをリロードしません。明示的に呼び出す必要がありますが、本当に必要な場合でも、実装するのはそれほど難しくありません。


5

Python 3を使用していて、importlibからリロードする人。

モジュールがリロードされないような問題が発生した場合...これは、pycを再コンパイルするのにしばらく時間がかかるためです(最大60秒)。



3

その他のオプション。Pythonのデフォルトでimportlib.reloadは、引数として渡されたライブラリが再インポートされるだけです。それはないだろう、あなたのlibにインポートというライブラリをリロードします。多くのファイルを変更し、インポートするパッケージが多少複雑な場合は、ディープリロードを実行する必要があります。

あなたが持っている場合はIPythonまたはJupyterがインストールされ、あなたは深いリロードすべてのLIBSの機能を使用することができます。

from IPython.lib.deepreload import reload as dreload
dreload(foo)

Jupyterがない場合は、シェルで次のコマンドを使用してインストールします。

pip3 install jupyter

importlibからのこのIpython dreloadとreload()はどちらもに不満を持っていreload() argument must be moduleます。カスタム関数インポートを使用していますが、機能していないようです。組み込みモジュールを使用しても機能します。:-(私がコードに加えた小さな変更ごとにiPythonをリロードするのは時間の無駄です...
m3nda '11

2

編集(Answer V2)

以前からの解決策は、リセット情報を取得するだけの場合に適していますが、すべての参照を変更するわけではありません(reload必要以上の変更はありません)。実際にすべての参照も設定するには、ガベージコレクターに移動し、そこで参照を書き換える必要がありました。今それは魅​​力のように機能します!

これ、GCがオフになっている場合、またはGCによって監視されていないデータを再ロードする場合には機能しないことに注意してください。GCを台無しにしたくない場合は、元の答えで十分かもしれません。

新しいコード:

import importlib
import inspect
import gc
from weakref import ref


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    # First, log all the references before reloading (because some references may be changed by the reload operation).
    module_tree = _get_tree_references_to_reset_recursively(module, module.__name__)

    new_module = importlib.reload(module)
    _reset_item_recursively(module, module_tree, new_module)


def _update_referrers(item, new_item):
    refs = gc.get_referrers(item)

    weak_ref_item = ref(item)
    for coll in refs:
        if type(coll) == dict:
            enumerator = coll.keys()
        elif type(coll) == list:
            enumerator = range(len(coll))
        else:
            continue

        for key in enumerator:

            if weak_ref_item() is None:
                # No refs are left in the GC
                return

            if coll[key] is weak_ref_item():
                coll[key] = new_item

def _get_tree_references_to_reset_recursively(item, module_name, grayed_out_item_ids = None):
    if grayed_out_item_ids is None:
        grayed_out_item_ids = set()

    item_tree = dict()
    attr_names = set(dir(item)) - _readonly_attrs
    for sub_item_name in attr_names:

        sub_item = getattr(item, sub_item_name)
        item_tree[sub_item_name] = [sub_item, None]

        try:
            # Will work for classes and functions defined in that module.
            mod_name = sub_item.__module__
        except AttributeError:
            mod_name = None

        # If this item was defined within this module, deep-reset
        if (mod_name is None) or (mod_name != module_name) or (id(sub_item) in grayed_out_item_ids) \
                or isinstance(sub_item, EnumMeta):
            continue

        grayed_out_item_ids.add(id(sub_item))
        item_tree[sub_item_name][1] = \
            _get_tree_references_to_reset_recursively(sub_item, module_name, grayed_out_item_ids)

    return item_tree


def _reset_item_recursively(item, item_subtree, new_item):

    # Set children first so we don't lose the current references.
    if item_subtree is not None:
        for sub_item_name, (sub_item, sub_item_tree) in item_subtree.items():

            try:
                new_sub_item = getattr(new_item, sub_item_name)
            except AttributeError:
                # The item doesn't exist in the reloaded module. Ignore.
                continue

            try:
                # Set the item
                _reset_item_recursively(sub_item, sub_item_tree, new_sub_item)
            except Exception as ex:
                pass

    _update_referrers(item, new_item)

元の回答

@bobinceの回答に記載されているように、別のモジュールにそのモジュールへの参照がすでにある場合(特に、asキーワードlikeでインポートされた場合import numpy as np)、そのインスタンスは上書きされません。

これは、構成モジュールの「白紙状態」を必要とするテストを適用するときに非常に問題があることがわかったため、の関数reset_moduleを使用し、宣言されたモジュールのすべての属性を再帰的に上書きするという名前importlibreload関数を記述しました。Pythonバージョン3.6でテストされています。

import importlib
import inspect
from enum import EnumMeta

_readonly_attrs = {'__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
               '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__get__',
               '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__',
               '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__',
               '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__',
               '__subclasshook__', '__weakref__', '__members__', '__mro__', '__itemsize__', '__isabstractmethod__',
               '__basicsize__', '__base__'}


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    new_module = importlib.reload(module)

    reset_items = set()

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    _reset_item_recursively(module, new_module, module.__name__, reset_items)


def _reset_item_recursively(item, new_item, module_name, reset_items=None):
    if reset_items is None:
        reset_items = set()

    attr_names = set(dir(item)) - _readonly_attrs

    for sitem_name in attr_names:

        sitem = getattr(item, sitem_name)
        new_sitem = getattr(new_item, sitem_name)

        try:
            # Set the item
            setattr(item, sitem_name, new_sitem)

            try:
                # Will work for classes and functions defined in that module.
                mod_name = sitem.__module__
            except AttributeError:
                mod_name = None

            # If this item was defined within this module, deep-reset
            if (mod_name is None) or (mod_name != module_name) or (id(sitem) in reset_items) \
                    or isinstance(sitem, EnumMeta):  # Deal with enums
                continue

            reset_items.add(id(sitem))
            _reset_item_recursively(sitem, new_sitem, module_name, reset_items)
        except Exception as ex:
            raise Exception(sitem_name) from ex

注:注意して使用してください!これらを非周辺モジュール(たとえば、外部で使用されるクラスを定義するモジュール)で使用すると、Pythonの内部問題(酸洗い/酸洗いの問題など)につながる可能性があります。


1

私にとってAbaqusの場合は、それが機能する方法です。あなたのファイルがClass_VerticesEdges.pyであると想像してください

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

この回答は、ここから直接コピーしたものです。ebanshi.cc
1942

0

Sublime Text内で何かを再読み込みしようとすると、多くの問題が発生しましたが、最終的に、このユーティリティを記述sublime_plugin.pyして、モジュールの再読み込みに使用するコードに基づいてSublime Textにモジュールを再読み込みすることができました。

以下では、名前にスペースが含まれているパスからモジュールをリロードすることを許可しています。その後、リロードした後、通常どおりにインポートすることができます。

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

初めて実行する場合、これによりモジュールがロードされますが、後でメソッド/関数を再度実行できる場合run_tests()は、テストファイルを再ロードします。Sublime Text(Python 3.3.6)では、インタプリタが閉じないため(Sublime Text、つまりPython3.3インタプリタを再起動しない限り)、これはよく起こります。


-1

もう1つの方法は、モジュールを関数にインポートすることです。このように、関数が完了すると、モジュールはガベージコレクションされます。


4
少なくともでグローバル参照が保持されているため、モジュールはガベージコレクションを取得しませんsys.modules
すべての労働者は必須です
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.