I have thousands of models in my package, each of them contains one class. Users can choose model they want to use by:
from myproject.type1.models.m1 import m1
Very inconvenient.
The subfolder looks like:
type1/
├── __init__.py
├── constant.py
├── decorator.py
├── models
│ ├── m1.py
│ ├── m2.py
│ ├── m3.py
...
│ ├── m999.py
So I write a module loader to load module dynamic:
class ModelLoader:
def __init__(self, model_path):
self.model_path = model_path
self.models = {}
def __getattribute__(self, __name: str) -> Any:
try:
return super().__getattribute__(__name)
except AttributeError:
if __name not in self.models:
try:
model_file = import_module(self.model_path + "." + __name)
model = getattr(model_file, __name)
self.models[__name] = model
return model
except ModuleNotFoundError:
raise AttributeError(f"Model {__name} not found")
else:
return self.models[__name]
With this, user can load module by just:
models = ModelLoader(__name__.rsplit(".", 1)[0] + ".models")
m1 = models.m1
m2 = models.m2
But this cause a problem.
Vscode or pycharm can not provide IntelliSense for m1 if it is imported by ModelLoader
.
Intellisense works:
not work:
How can I let IDE know class ModelLoader
have a member m1
and is defined in myproject.type1.models.m1
?
I do not import all module in my package’s __init__
since it will harm user experience, it takes about 30s to import all models.
2
Answers
VSCode uses static analysis for it’s IntelliSense feature,
which means it analyzes the code without actually running it.
If you want to have intellisense support, you have to add the import codes at the beginning of your scripts like
from myproject.type1.models import m1, m2, m3
Add all the modules you want IntelliSense for.
You can try and generate a
.pyi
file based on thetype1
directory.Pylance can use that to feed its static code analysis.