You can engineer sys.modules
to do this.
If you have two files, version_file.py, which contain version information for two different modules/projects.
Import the first:
# NB use sys.path.insert(0, ...) to make this path the first path to be searched by the framework
sys.path.insert(0, str(project_a_dir_path)) # NB parent dir of version_file.py
if 'version_file' in sys.modules:
# ... deal with this: raise exception, delete key, log, etc. (see explanation below)
project_a_version_file_mod = importlib.import_module('version_file')
# make your own chosen key point to this newly imported module:
sys.modules['project_a_version_file_mod'] = sys.modules['version_file']
del sys.modules['version_file']
# preferably, delete from sys.path if this entry won't be used again:
del sys.path[0]
Then you process the other:
sys.path.insert(0, str(project_b_dir_path)) # NB parent dir of **its** version_file.py
project_b_version_file_mod = importlib.import_module('version_file')
sys.modules['project_b_version_file_mod'] = sys.modules['version_file']
del sys.modules['version_file']
# preferably, delete entry from sys.path
del sys.path[0]
You now have two imported modules, project_a_version_file_mod
and project_b_version_file_mod
. Assuming both have an attr "version" you can get their respective values: project_a_version_file_mod.version
and project_b_version_file_mod.version
.
I'm not seeing anything problematic in this technique but would be interested to hear if anyone can point out any issues.
Idiosyncracies and traps of the sys.modules dict
NB it important to know, according to my experiments, that if importlib.import_module
looks at sys.modules
and finds a key there already for the next module it's being asked to add, it just ignores the new instruction! I find this quite strange, but that appears to be the case.
For this reason, if you don't delete (del sys.modules['version_file']
) in the first import operation above, the second will fail (silently) to import on import_module
, so in that case project_b_version_file_mod
would in fact also be pointing at the version file module project_a_version_file_mod
.
Similarly, if there is already an entry with key "version_file" before the first operation, the import operation wouldn't happen. That is why it is important to deal with that eventuality.
Idiosyncracies and traps of the sys.path list
NB2 Above, I recommend removing the entry added to sys.path
enabling the module to be imported, after doing the import. The objection might then be raised "but supposing that added path was already present in sys.path?".
The answer to that is that sys.path
is a list
, not a set
, so you can actually have multiple identical path entries, which is generally an undesirable thing, but which in this case makes this handling rather simple: by removing the added path you can guarantee you will return sys.path
to the way it was before.