0

In a project, I want to dynamically import the right module based on a version-number. For this I'm using importlib, and works find as long as the package is part of the source.

AdminApi = import_module(f"{self.version}", "AdminApi").AdminApi

The folder-structure looks like:

Admin-Package / 
    - __init__.py  # Contains dynamic class loader
    - admin64/
        - __init__.py  # contains AdminApi v6.4
        - ...
    - admin65/...
        - __init__.py  # contains AdminApi v6.5
        - ...

However, now I find myself needing to decouple the code into its own package to re-use in another project. So I've packaged this part of the source. This however seems to cause path-related issues. This seems to mean that importlib cannot help me.

So far, thanks to: https://stackoverflow.com/a/54138717/5731101 I've come to this point:

import importlib
from pathlib import Path

path = Path(__file__).resolve().parent
script_path = os.path.join(path, version, '__init__.py')

spec = importlib.util.spec_from_file_location(f"AdminApi", script_path)
AdminApi = importlib.util.module_from_spec(spec)
spec.loader.exec_module(AdminApi)

Unfortunately the spec.loader.excec_module fails with error: ModuleNotFoundError: No module named 'AdminApi' Even thought the class is clearly available in the file supplied via the path.

I would be grateful if anyone can help me out on this.

3
  • Just a q: what's wrong with if version == 64: import AdminApi64, etc? If you only have a few versions your want to handle I would find that more readable, and it would avoid messing with anything like importlib. Ofc if this dynamic importing is a feature, it might not be a good solution Commented Nov 25, 2021 at 16:27
  • That's a fair remark, perhaps I'm overcomplicating. It would however be a great feature going forward depending on the amount af variations we end up with. It seems the AdminApi we talk to seems to have some minor changes on every update - which is every month. Commented Nov 25, 2021 at 17:06
  • 1
    Fair enough. If you only ever need to talk to one AdminApi I would just call it Admin and replace it every time. But I take it in your use case you need multiple access.. In any case you've got a solution which works fine :) (the other option btw might be using admin = __import__(f"Admin{self.version}") (equivalent to import f"Admin{self.version}" as admin if import allowed that. I don't know, but I suspect that avoiding importlib and going higher level might fix it. Commented Nov 25, 2021 at 18:12

1 Answer 1

0

I decided to try another tool in the toolbox of importlib Based on this answer: https://stackoverflow.com/a/67692/5731101

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("AdminAPI", "/path/to/file.py").load_module()
foo.AdminAPI()

This approach had no problems detecting the class and simply imported everything correctly.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.