Question¶
i want to vendor a python module “plugget” with a plugin, plugget can install other python modules
i want it to install itself if there is a more recent version. if it does so, it would have to reload the python modules. would a simple del imported modules with name contain plugget do this? are there other recommended ways? what are the pros and cons. i know a simple reload doesn’t always does the trick for some reason.
also, how can i ensure it wont try to import the outdated plugget that is vendored with the plugin?
Answer¶
Reloading plugget After Self-Upgrade¶
Using del sys.modules[name] to remove plugget from the module cache won’t fully reset the state if other modules or objects still hold references to it. Here’s why:
- Pros:
- It forces Python to re-import the module from disk.
- It’s simple and works in many basic cases.
- Cons:
- Any existing references (e.g.
from plugget import something) will still point to the old version. - Dependencies of
pluggetwon’t be reloaded unless you explicitly do so. - It can lead to subtle bugs if the module maintains internal state or caches.
- Any existing references (e.g.
A more robust approach is:
import sys
import importlib
if 'plugget' in sys.modules:
importlib.reload(sys.modules['plugget'])
else:
import plugget
But even importlib.reload() has limitations:
- It re-executes the module’s code but doesn’t update existing references.
- It doesn’t reload submodules or dependencies unless you do that manually.
Avoiding the Vendored Version¶
To ensure Python doesn’t import the outdated vendored plugget, you can:
- Manipulate
sys.path:- Insert the path to the updated
plugget(e.g. from site-packages) before the vendored path. - Or remove the vendored path entirely if the update succeeds.
- Insert the path to the updated
- Use
importlib.util.find_spec()to inspect where the module is coming from:
- Namespace isolation:
- Consider using a subprocess to run the plugin logic with a clean import environment.
- This avoids the complexity of in-process reloading altogether.
I could add the vendor folder to python path, import and install, then remove from path
- I could vendor the module under a different name, e.g. plugget_vendored
Final Thoughts¶
consider:
- Designing it to be stateless or restart-safe.
- Using subprocesses or even importlib.machinery.SourceFileLoader to load a fresh copy under a different name.
Notes¶
- plugget’s
_requirements.pyaction already vendors py-pip, see code
_utils.pydoesn’t use the vendored version, but the import is wrapped in a local method so it should be fine.
This approach doesn’t handle any module reload. - This could work for unreal plugins, but Blender addons & Maya plugins aren’t in the PATH so only support a single python file. This requires a copy paste code solution, or dynamic adding to the pwath. At least maya has a workaround with Maya modules but it’d be nice to have it for plugins too.
- the Maya plugin template already has an installer, so we can use this. (I think the installer already installs dependencies)
- The new Blender extension support vendoring dependencies, so lets ignore Blender addon