your programing

모듈을 어떻게 언로드 (다시로드)합니까?

lovepro 2020. 9. 29. 08:17
반응형

모듈을 어떻게 언로드 (다시로드)합니까?


오래 실행되는 Python 서버가 있고 서버를 다시 시작하지 않고도 서비스를 업그레이드 할 수 있기를 원합니다. 이를 수행하는 가장 좋은 방법은 무엇입니까?

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

reload내장 함수 를 사용하여 이미 가져온 모듈을 다시로드 할 수 있습니다 .

from importlib import reload  # Python 3.4+ only.
import foo

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

Python 3에서는 모듈 reload로 이동되었습니다 imp. 3.4에서는 imp찬성이 사용됩니다 importlib, 그리고 reload후자에 추가되었습니다. 3 이상을 대상으로하는 경우 호출 할 때 적절한 모듈을 참조 reload하거나 가져올 수 있습니다.

나는 이것이 당신이 원하는 것이라고 생각합니다. Django의 개발 서버와 같은 웹 서버는이를 사용하므로 서버 프로세스 자체를 다시 시작하지 않고도 코드 변경의 영향을 확인할 수 있습니다.

문서에서 인용하려면 :

Python 모듈의 코드가 다시 컴파일되고 모듈 수준 코드가 다시 실행되어 모듈 사전의 이름에 바인딩 된 새 개체 집합을 정의합니다. 확장 모듈의 초기화 기능은 두 번째로 호출되지 않습니다. Python의 다른 모든 객체와 마찬가지로 이전 객체는 참조 횟수가 0으로 떨어진 후에 만 ​​회수됩니다. 모듈 네임 스페이스의 이름은 새롭거나 변경된 개체를 가리 키도록 업데이트됩니다. 이전 개체에 대한 다른 참조 (예 : 모듈 외부의 이름)는 새 개체를 참조하도록 리 바인드되지 않으며 원하는 경우 발생하는 각 네임 스페이스에서 업데이트해야합니다.

질문에서 언급했듯이 클래스가 모듈에 상주하는 Foo경우 객체 를 재구성 Foo해야 foo합니다.


Python 3.0–3.3에서는 다음을 사용합니다. imp.reload(module)

BDFL는대답 이 질문을.

그러나 imp3.4에서는importlib ( @Stefan 에게 감사드립니다 ! ) 찬성하여 더 이상 사용되지 않습니다 .

나는 생각한다 그러므로 당신이 지금 사용하는 거라고, importlib.reload(module)잘 모르겠어요하지만,.


순수한 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

세 번째 참조는 getrefcount () 함수의 아티팩트이기 때문입니다.


reload(module)하지만 완전히 독립형 인 경우에만 가능합니다. 다른 것이 모듈 (또는 모듈에 속한 객체)에 대한 참조를 가지고 있다면, 이전 코드가 예상보다 오래 걸려서 발생하는 미묘하고 흥미로운 오류가 발생하고 isinstance다른 버전의 같은 코드.

단방향 종속성이있는 경우 다시로드 된 모듈에 종속 된 모든 모듈을 다시로드하여 이전 코드에 대한 모든 참조를 제거해야합니다. 그런 다음 다시로드 된 모듈에 의존하는 모듈을 재귀 적으로 다시로드합니다.

If you have circular dependencies, which is very common for example when you are dealing with reloading a package, you must unload all the modules in the group in one go. You can't do this with reload() because it will re-import each module before its dependencies have been refreshed, allowing old references to creep into new modules.

The only way to do it in this case is to hack sys.modules, which is kind of unsupported. You'd have to go through and delete each sys.modules entry you wanted to be reloaded on next import, and also delete entries whose values are None to deal with an implementation issue to do with caching failed relative imports. It's not terribly nice but as long as you have a fully self-contained set of dependencies that doesn't leave references outside its codebase, it's workable.

It's probably best to restart the server. :-)


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

For Python 2 use built-in function reload():

reload(module)

For Python 2 and 3.2–3.3 use reload from module imp:

import imp
imp.reload(module)

But imp is deprecated since version 3.4 in favor of importlib, so use:

import importlib
importlib.reload(module)

or

from importlib import reload
reload(module)

The following code allows you Python 2/3 compatibility:

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

The you can use it as reload() in both versions which makes things simpler.


The accepted answer doesn't handle the from X import Y case. This code handles it and the standard import case as well:

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")

In the reloading case, we reassign the top level names to the values stored in the newly reloaded module, which updates them.


This is the modern way of reloading a module:

from importlib import reload

If you want to support versions of Python older than 3.4, try this:

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+

To use it, run reload(MODULE), replacing MODULE with the module you want to reload.

For example, reload(math) will reload the math module.


If you are not in a server, but developing and need to frequently reload a module, here's a nice tip.

First, make sure you are using the excellent IPython shell, from the Jupyter Notebook project. After installing Jupyter, you can start it with ipython, or jupyter console, or even better, jupyter qtconsole, which will give you a nice colorized console with code completion in any OS.

Now in your shell, type:

%load_ext autoreload
%autoreload 2

Now, every time you run your script, your modules will be reloaded.

Beyond the 2, there are other options of the autoreload magic:

%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.

For those like me who want to unload all modules (when running in the Python interpreter under Emacs):

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

More information is in Reloading Python modules.


Enthought Traits has a module that works fairly well for this. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

It will reload any module that has been changed, and update other modules and instanced objects that are using it. It does not work most of the time with __very_private__ methods, and can choke on class inheritance, but it saves me crazy amounts of time from having to restart the host application when writing PyQt guis, or stuff that runs inside programs such as Maya or Nuke. It doesn't work maybe 20-30 % of the time, but it's still incredibly helpful.

Enthought's package doesn't reload files the moment they change - you have to call it explicitely - but that shouldn't be all that hard to implement if you really need it


Those who are using python 3 and reload from importlib.

If you have problems like it seems that module doesn't reload... That is because it needs some time to recompile pyc (up to 60 sec).I writing this hint just that you know if you have experienced this kind of problem.


2018-02-01

  1. module foo must be imported successfully in advance.
  2. from importlib import reload, reload(foo)

31.5. importlib — The implementation of import — Python 3.6.4 documentation


Other option. See that Python default importlib.reload will just reimport the library passed as an argument. It won't reload the libraries that your lib import. If you changed a lot of files and have a somewhat complex package to import, you must do a deep reload.

If you have IPython or Jupyter installed, you can use a function to deep reload all libs:

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

If you don't have Jupyter, install it with this command in your shell:

pip3 install jupyter

for me for case of Abaqus it is the way it works. Imagine your file is 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'])

Another way could be to import the module in a function. This way when the function completes the module gets garbage collected.


I got a lot of trouble trying to reload something inside Sublime Text, but finally I could wrote this utility to reload modules on Sublime Text based on the code sublime_plugin.py uses to reload modules.

This below accepts you to reload modules from paths with spaces on their names, then later after reloading you can just import as you usually do.

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()

If you run for the first time, this should load the module, but if later you can again the method/function run_tests() it will reload the tests files. With Sublime Text (Python 3.3.6) this happens a lot because its interpreter never closes (unless you restart Sublime Text, i.e., the Python3.3 interpreter).

참고URL : https://stackoverflow.com/questions/437589/how-do-i-unload-reload-a-module

반응형