Search code examples
pythondel

How to delete/unload all modules mentioned in a list=


I want to unload all submodules that belong to a specifc module, because it conflicts with another module. Here's what I do:

mainmodule_submodules = [key for key in sys.modules if key.startswith('mainmodule')]
for mainmodule_submodule in mainmodule_submodules:
    del mainmodule_submodule # deletes the variable mainmodule_submodule instead of the submodule that's stored in it
    del sys.modules[mainmodule_submodule]

The problem is that this deletes the variable mainmodule_submodule that's created by the for loop instead of the module that's stored a the value of mainmodule_submodule. How do I do this?


Solution

  • I am not sure what your exact use case is. Dealing with unloading modules (and possibly reloading them later again) sounds very error-prone. I rather suggest refactoring your code in order to reduce technical debts instead of implementing a workaround.

    However, if you want to unload a module just use del sys.modules[module] (and del globals()[module] if you don't want the imported module available anymore).

    Note: I shortened your variable names for better readability in this example context.

    import os
    import sys
    
    print(os.path.join("a", "b", "c"))
    
    modules = [key for key in sys.modules if key.startswith('os')]
    
    for module in modules:
        if module in sys.modules:
            print(f"Unloading {module}")
            del sys.modules[module]
            if module in globals():
                del globals()[module]
    
    # this should fail
    print(os.path.join("a", "b", "c"))
    

    Without knowing where your conflicts are, if in your own code, maybe you could avoid conflicts by using aliases.

    import os as os_alias
    
    print(os_alias.pathjoin("a", "b", "c"))