Reloading packages (and their submodules) recursively in Python

In Python, you can reload the module as follows:

import foobar import importlib importlib.reload(foobar) 

This works for .py files, but for Python packages it reloads the package and not any of the nested submodules.

With package:

  • foobar/__init__.py
  • foobar/spam.py
  • foobar/eggs.py

Python Script:

 import foobar # assume `spam/__init__.py` is importing `.spam` # so we dont need an explicit import. print(foobar.spam) # ok import importlib importlib.reload(foobar) # foobar.spam WONT be reloaded. 

Do not suggest this error, but sometimes it is useful to reload the package and all its submodules. (If you want to edit the module when the script is executed).

What are some good ways to recursively reload a package in Python?

Notes:

  • For the purposes of this question, take the latest Python3.x

    (currently using importlib )

  • Permission for this may require some changes to the modules themselves.
  • Assume that importing templates is not used ( from foobar import * ), as they can complicate the reload logic.
+6
source share
2 answers

Here is a function that recursively loads a package. Double checked that the updated modules are updated in the modules where they are used, and that problems with infinite recursion are checked.

One of them is launching a package (which makes sense only for packages)

 import os import types import importlib def reload_package(package): assert(hasattr(package, "__package__")) fn = package.__file__ fn_dir = os.path.dirname(fn) + os.sep module_visit = {fn} del fn def reload_recursive_ex(module): importlib.reload(module) for module_child in vars(module).values(): if isinstance(module_child, types.ModuleType): fn_child = getattr(module_child, "__file__", None) if (fn_child is not None) and fn_child.startswith(fn_dir): if fn_child not in module_visit: # print("reloading:", fn_child, "from", module) module_visit.add(fn_child) reload_recursive_ex(module_child) return reload_recursive_ex(package) # example use import os reload_package(os) 
+3
source

Something like this, maybe?

 import importlib import types def reloadall(module): importlib.reload(module) for child in module: if isinstance(child, types.ModuleType): reloadall(child) 
-1
source

Source: https://habr.com/ru/post/981426/


All Articles