I have a program that supports different communication protocols. The idea is, that the user chooses the protocol during startup and then the module supporting the respective protocol is imported.
The function below populates the protocol
module with all functions and variables from the user-chosen protocol.
protocol.py
:
def provide_protocol( name ): for key, val in vars( __import__( name ) ).items(): if key.startswith( "__" ) and key.endswith( "__" ): continue vars()[key] = val importlib.invalidate_caches()
name
is provided by the user at program startup.
The issue is, that protocol.py
is imported before this function is run and the program is not able to access the newly populated functions in this previously empty module.
Using invalidate_caches()
from the importlib
module does not change this.
I also tried, to remove protocol.py
and create the whole module dynamically using importlib
, but this also did not succeed:
__init__.py
:
protocol = None def provide_protocol( name ): protocol = importlib.import_module( name ) importlib.invalidate_caches()
The problem seems to be identical, because if I import protocol
, it seems to be None
.
Advertisement
Answer
Both of your functions don’t don’t return anything useful (they both return None
). Your first function tries to modify vars
, but that won’t do anything useful. From the docs:
Without an argument,
vars()
acts likelocals()
. Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.
Note, if you had done that in a global scope, locals() is globals()
, so those modifications would take effect, but since you are doing it in a function, nothing happens.
In your second function, you assign to a local variable protocol
then don’t do anything with it. The global variable protocol
will remain None
. You should just return protocol
then use it like:
def provide_protocol( name ): protocol = importlib.import_module( name ) importlib.invalidate_caches() return protocol protocol = provide_protocol(name)
Note, in both cases, the module would still be in the cache, so:
import sys protocol = sys.modules[name]
Would have retrieved it. But you should just explicitly return and assign it to whatever name you want.