905

I have a long-running Python server and would like to be able to upgrade a service without restarting the server. What's the best way do do this?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
Mark Harrison
  • 267,774
  • 112
  • 308
  • 434
  • 63
    Memo tip: "import" doesn't mean "load", it means "load if not loaded yet and then import into namespace". – Kos Jan 10 '13 at 11:30
  • 4
    the question should not include 'unload' as that is not possible in python yet - reload is however a known paradigm as answered below – rjmoggach May 29 '14 at 04:08
  • 2
    What if you want to "unload" because trying to delete a .pyc file is being used by the code? – darkgaze Sep 29 '16 at 13:48
  • I had the same problem when using a dynamic module in py2exe app. As py2exe always keep bytecode in zip directory reload was not working. But I found a working solution using import_file module. Now my application is working fine. – Pritam Pan Mar 05 '16 at 21:57

21 Answers21

922

You can reload a module when it has already been imported by using the reload builtin function (Python 3.4+ only):

from importlib import reload  
import foo

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

In Python 3, reload was moved to the imp module. In 3.4, imp was deprecated in favor of importlib, and reload was added to the latter. When targeting 3 or later, either reference the appropriate module when calling reload or import it.

I think that this is what you want. Web servers like Django's development server use this so that you can see the effects of your code changes without restarting the server process itself.

To quote from the docs:

Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called a second time. As with all other objects in Python the old objects are only reclaimed after their reference counts drop to zero. The names in the module namespace are updated to point to any new or changed objects. Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.

As you noted in your question, you'll have to reconstruct Foo objects if the Foo class resides in the foo module.

Nicolas Gervais
  • 21,923
  • 10
  • 61
  • 96
cdleary
  • 63,281
  • 49
  • 155
  • 190
  • 11
    actually, the django dev server restarts itself when you change a file .. (it restarts the server, not just reloads the module) – hasen Jan 13 '09 at 06:36
  • 1
    Ah, you're right -- looks like they just reboot the server thread. Well, just know that they *could* use reload, I guess. :-) – cdleary Jan 16 '09 at 11:55
  • 32
    where is this "is_changed" function coming from? i see no documentation on it and it doesn't run in my Python 3.1.3 environment, nor does it run in 2.6.4. – jedmao Jun 17 '11 at 14:29
  • On the iPython command line `reload` doesn't appear to follow the import dependency chain, it only reloads the module(s) indicated by the argument. – hobs Mar 19 '12 at 06:55
  • Python 3 changed it to import imp / imp.reload(foo) – Yuri Astrakhan Apr 05 '12 at 14:35
  • 5
    no cdleary, Django can't just use reload: http://pyunit.sourceforge.net/notes/reloading.html – raylu Oct 05 '12 at 05:54
  • 1
    FYI, in Python 2 at least, you can simply do `reload(foo)` instead of `foo = reload(foo)`. – John M. Feb 07 '13 at 18:06
  • 2
    Strange. The answer only deals with reloading. What about unloading? – fatuhoku Oct 16 '13 at 10:58
  • 3
    How do I use reload for an import like "from a.b.c import someClass as abcClass"... reload(abcClass) complains that it isn't defined. – nmz787 Sep 04 '14 at 21:20
  • 4
    reload is not sufficient for modules with dependencies. See bobince below: http://stackoverflow.com/a/438845/456878. This has bitten me before and wasted a good 10 minutes. – Doug Bradshaw Feb 18 '15 at 13:59
  • This isn't possible for C extensions in Windows because the `.pyd` file is in use and cannot be updated. – ivan_pozdeev Oct 22 '16 at 12:10
  • 2
    How is the top answer for this question? It doesn't work in my py27 and/or py34 @jedmao did you ever find out where "is_changed" is coming from? – James Draper Dec 13 '16 at 17:35
  • 2
    @JamesDraper nope, never found out where `is_changed` came from... or I forgot. It's been so long ago. – jedmao Dec 16 '16 at 23:16
  • 4
    FYI, reload is a source of evil. For example, all instances of objects created with the first import will reference the old class: `import foo; bar = foo.Bar(); reload(foo); assert isinstance(bar, foo.Bar)` will raise AssertError – Tiago Coutinho Jul 09 '17 at 07:27
  • 9
    @jedmao @JamesDraper I am pretty sure the `is_changed` function is just an arbitrary function that you would have to write; it is not a built-in. For example, it could possibly open the file corresponding to the module that you are importing and diff it with a cached version to see if it changed. – James Mchugh Sep 11 '18 at 14:38
  • This method might not override other modules' references to the reloaded module. See https://stackoverflow.com/a/61617169/2642356 for a solution to that. – EZLearner May 05 '20 at 15:57
  • I have to ask. What will happen after the program has been compiled? – Jdeep Nov 28 '20 at 18:14
260

In Python 3.0–3.3 you would use: imp.reload(module)

The BDFL has answered this question.

However, imp was deprecated in 3.4, in favour of importlib (thanks @Stefan!).

I think, therefore, you’d now use importlib.reload(module), although I’m not sure.

Community
  • 1
  • 1
Paul D. Waite
  • 89,393
  • 53
  • 186
  • 261
106

It can be especially difficult to delete a module if it is not pure Python.

Here is some information from: How do I really delete an imported module?

You can use sys.getrefcount() to find out the actual number of references.

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

Numbers greater than 3 indicate that it will be hard to get rid of the module. The homegrown "empty" (containing nothing) module should be garbage collected after

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

as the third reference is an artifact of the getrefcount() function.

Honest Abe
  • 7,434
  • 4
  • 45
  • 59
Gregg Lind
  • 18,936
  • 15
  • 63
  • 80
  • 4
    I just discovered that if the module is a part of a package, you have to delete it there as well: `setattr(package, "empty", None)` – u0b34a0f6ae May 11 '10 at 12:33
  • 8
    This is the correct solution, especially if you have a package with nested modules. `reload()` only reloads the top-most module, and anything inside it will not be reloaded unless you first delete it from sys.modules. – Cerin Dec 05 '16 at 20:05
80

reload(module), but only if it's completely stand-alone. If anything else has a reference to the module (or any object belonging to the module), then you'll get subtle and curious errors caused by the old code hanging around longer than you expected, and things like isinstance not working across different versions of the same code.

If you have one-way dependencies, you must also reload all modules that depend on the reloaded module to get rid of all the references to the old code. And then reload modules that depend on the reloaded modules, recursively.

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. :-)

HoldOffHunger
  • 10,963
  • 6
  • 53
  • 100
bobince
  • 498,320
  • 101
  • 621
  • 807
  • 1
    Isn't dreload specifically for that scenario? – Josh May 31 '12 at 21:10
  • 1
    @Josh: nope, it's for reloading a package tree, and even then it only works as long as the package doesn't have outside/circular dependencies. – bobince Jun 02 '12 at 10:29
  • 1
    Can you elaborate the part with `None` values because I'm running exactly into this issue: I'm deleting items from `sys.modules` and after re-import some imported dependencies are `None`. – schlamar Mar 26 '13 at 10:15
  • @shclamar: See http://stackoverflow.com/questions/1958417/why-are-there-dummy-modules-in-sys-modules (and the links from there) for background. It's unclear to me (even looking at the import.c code) how the `None` entries managed to make their way back through the import mechanism when the 'real' entries were deleted, and I can't seem to make it happen on 2.7; in future certainly it's no longer a problem as implicit relative imports have gone away. In the meantime, deleting all entries with `None` value does seem to fix it. – bobince Mar 26 '13 at 15:13
  • it would be nicer for newbies if someone could reference where or from which library the function came from,in the case of this answer 'reload(module)' – Eliethesaiyan Apr 20 '16 at 13:18
  • 1
    @Eliethesaiyan: do you mean the `reload` function? It is built-in, you don't have to import any library. – bobince Apr 22 '16 at 14:07
  • @bobince,i think you are right for reload.. i previously used it from package imp – Eliethesaiyan Apr 27 '16 at 00:57
  • I wrote a function below that does overrides the previous module's contents with the new one's and hence deals with the problem @bobince rightfully mentioned. See https://stackoverflow.com/a/61617169/2642356 – EZLearner May 05 '20 at 15:46
71

For Python 2 use built-in function reload:

reload(module)

For Python 2 and Python 3.23.3 use reload from module imp:

import imp
imp.reload(module)

For Python ≥3.4, imp is deprecated in favor of importlib, so use this:

import importlib
importlib.reload(module)

or:

from importlib import reload
reload(module)

TL;DR:

Python ≥ 3.4: importlib.reload(module)
Python 3.2 — 3.3: imp.reload(module)
Python 2: reload(module)

goetzc
  • 1,443
  • 1
  • 23
  • 29
  • 2
    to handle any of these cases: `from six import reload_module` (need to `pip install six` first of course) – Anentropic Oct 30 '17 at 16:46
  • @Anentropic: It is good advice to recommend using six package, but the syntax is `from six.moves import reload_module` ([doc](https://pythonhosted.org/six/#module-six.moves)) – x0s Jan 04 '18 at 20:32
68
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]
Daniel
  • 39,063
  • 4
  • 50
  • 76
Kumaresan
  • 705
  • 5
  • 2
  • 3
    +1. My goal was to run nose tests within python. After I had loaded a module and renamed some functions, the old names remained when calling `nose.run()`, even after `reload(my_module)` `%run my_module` – Peter D Sep 11 '12 at 19:46
  • 7
    If your module imports it's own submodules, you may need to delete those too. Something like `[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]`. – drevicko Jun 24 '14 at 09:00
  • 1
    I don't think that unloads the module. On Python 3.8: `import sys; import json; del sys.modules['json']; print(json.dumps([1]))` and json module is still working even though it is not in the sys.modules anymore. – Seperman May 16 '20 at 06:37
  • yea, I noticed an underscored sys.modules['_json'] entry, and it still prints out after taking that into account ```for mod in [ m for m in sys.modules if m.lstrip('_').startswith('json') ]: del sys.modules[mod]``` – Doyousketch2 Oct 15 '20 at 06:38
  • yep. Even w/ more aggressive bookeeping, removing entries along with all their dependencies doesn't remove module's capability to function. ```before = [mod for mod in sys.modules] ; import json ; after = [mod for mod in sys.modules if mod not in before] ; for mod in [ m for m in sys.modules if m in after ]: del sys.modules[mod]``` ( code-block didn't keep newlines. ; denotes newline ) – Doyousketch2 Oct 15 '20 at 06:43
25

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.

Matt Clarkson
  • 12,834
  • 9
  • 53
  • 84
22

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.

Joseph Garvin
  • 18,725
  • 17
  • 83
  • 150
  • Noticed an issue, globals() refers to the module you define this function in, so if you define it in a module different than the one you call it in this doesn't work. – Joseph Garvin Oct 11 '14 at 20:29
  • For interactive, after `>>> from X import Y` to reload do `>>> __import__('X', fromlist='Y')` – Bob Stein Jan 29 '15 at 17:43
  • @BobStein-VisiBone, is there a way to make that work when `fromlist='*'`? – Mike C Jul 28 '15 at 19:55
  • Good question, don't know @MikeC. By the way I'm trending to cease almost all use of `from` in import statements. Just stark `import ` and explicit package.symbol in the code. Realize this may not always be possible or desirable. (Here's one exception: from future import print_function.) – Bob Stein Jul 29 '15 at 00:21
  • Mike C: what works for me is `foo = reload(foo); from foo import *` – rampion Oct 19 '16 at 13:09
  • Add `import importlib` and `importlib.reload( ...` – George Fisher Mar 05 '17 at 18:37
20

This is the modern way of reloading a module:

from importlib import reload

If you want to support versions of Python older than 3.5, 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.

Richie Bendall
  • 3,783
  • 2
  • 24
  • 36
  • 4
    Or just do `from importlib import reload`. Then you can do `reload(MODULE_NAME)`. There is no need for this function. – pault Feb 02 '18 at 18:39
  • I believe `modulereload(MODULE_NAME)` is more self-explanatory than just `reload(MODULE_NAME)` and has a lower chance to conflict with other functions. – Richie Bendall Jul 17 '18 at 22:30
  • @RichieBendall Sorry, but this answer is completely wrong. The reload() function takes module object, not module name... Read the docs: https://docs.python.org/3/library/importlib.html#importlib.reload And I agree with @ pault - this "as modulereload" is superflous. – mbdevpl Aug 01 '18 at 01:09
  • I've changed my answer to reflect your opinion. – Richie Bendall Aug 04 '18 at 04:34
20

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.

Sure, it will also work on a Jupyter Notebook.

neves
  • 20,547
  • 15
  • 108
  • 137
8

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.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
  • Actually that doesn't seem to work reliably (in 2.6) because not everything in `sys.modules.values()` is a module. For example: >>> type(sys.modules.values()[1]) So if I try to run that code it falls over (I Know its not meant as a practical solution, just pointing that out). – Francis Davey Jun 18 '10 at 08:04
  • It doesn't even work in earlier pythons - as written. I had to exclude some names. I'll update the post when I move that code to my new computer. –  Jun 19 '10 at 05:32
  • 2
    Works fine in Python 2.7 after some modifications: `if mod and mod.__name__ != "__main__": imp.reload(mod)` – Czarek Tomczak Sep 15 '12 at 14:24
  • 2
    This works well for me: import imp [reload(m) for m in sys.modules.values() if m and not "__" in m.__name__ and not imp.is_builtin(m.__name__)] – Patrick Wolf Jun 17 '15 at 23:40
5

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

flipthefrog
  • 112
  • 1
  • 3
5

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.

PythonMan
  • 517
  • 7
  • 15
4

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

AbstProcDo
  • 14,203
  • 14
  • 49
  • 94
4

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
IanS
  • 13,182
  • 7
  • 49
  • 75
neves
  • 20,547
  • 15
  • 108
  • 137
  • Both this Ipython dreload and reload() from importlib does complain with `reload() argument must be module`. I'm using a custom function import and doesn't seem to work. Using built-in modules does work. :-( it's a waste of time being reloading iPython for every little change i made to my code ... – m3nda Aug 11 '18 at 13:58
2

Edit (Answer V2)

The solution from before is good for just getting the reset information, but it will not change all the references (more than reload but less then required). To actually set all the references as well, I had to go into the garbage collector, and rewrite the references there. Now it works like a charm!

Note that this will not work if the GC is turned off, or if reloading data that's not monitored by the GC. If you don't want to mess with the GC, the original answer might be enough for you.

New code:

import importlib
import inspect
import gc
from enum import EnumMeta
from weakref import ref


_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.
    """

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

Original Answer

As written in @bobince's answer, if there's already a reference to that module in another module (especially if it was imported with the as keyword like import numpy as np), that instance will not be overwritten.

This proved quite problematic to me when applying tests that required a "clean-slate" state of the configuration modules, so I've written a function named reset_module that uses importlib's reload function and recursively overwrites all the declared module's attributes. It has been tested with Python version 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

Note: Use with care! Using these on non-peripheral modules (modules that define externally-used classes, for example) might lead to internal problems in Python (such as pickling/un-pickling issues).

David Ghandehari
  • 499
  • 3
  • 12
EZLearner
  • 1,140
  • 10
  • 23
2

If you encounter the following error, this answer may help you to get a solution:

Traceback (most recent call last): 
 File "FFFF", line 1, in  
NameError: name 'YYYY' is not defined

OR

Traceback (most recent call last):
 File "FFFF", line 1, in 
 File "/usr/local/lib/python3.7/importlib/__init__.py", line 140, in reload
   raise TypeError("reload() argument must be a module")
TypeError: reload() argument must be a module

In case you have an import like the one below, you may need to use the sys.modules to get the module you want to reload:

  import importlib
  import sys

  from YYYY.XXX.ZZZ import CCCC
  import AAA.BBB.CC


  def reload(full_name)
    if full_name in sys.modules:
      importlib.reload(sys.modules[full_name])


  reload('YYYY.XXX.ZZZ') # this is fine in both cases
  reload('AAA.BBB.CC')  

  importlib.reload(YYYY.XXX.ZZZ) # in my case: this fails
  importlib.reload(AAA.BBB.CC)   #             and this is ok

The main issue is that the importlib.reload accepts module only not string.

minus one
  • 324
  • 1
  • 17
1

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'])
Matt S
  • 27
  • 4
  • This answer is a direct copy from here: http://ebanshi.cc/questions/1942/how-do-i-unload-reload-a-python-module – SiHa Oct 12 '16 at 07:39
1

Removing modules from sys.modules requires 'None' types to be deleted as well.

Method 1:

import sys
import json  ##  your module

for mod in [ m for m in sys.modules if m.lstrip('_').startswith('json') or sys.modules[m] == None ]: del sys.modules[mod]

print( json.dumps( [1] ) )  ##  test if functionality has been removed

Method 2, using bookkeeping entries, to remove all dependencies:

import sys

before_import = [mod for mod in sys.modules]
import json  ##  your module
after_import = [mod for mod in sys.modules if mod not in before_import]

for mod in [m for m in sys.modules if m in after_import or sys.modules[m] == None]: del sys.modules[mod]

print( json.dumps( [2] ) )  ##  test if functionality has been removed

Optional, just to be certain all entries are out, if you so choose:

import gc
gc.collect()
Doyousketch2
  • 796
  • 4
  • 11
0

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

hackbot89
  • 41
  • 1
  • 5
0

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

user
  • 5,816
  • 7
  • 53
  • 105