From c0145e5fe1a8abdcfe8f95bdb0f6cad647db0465 Mon Sep 17 00:00:00 2001 From: Joe Gordon Date: Thu, 12 Mar 2015 20:43:36 -0700 Subject: [PATCH] Make non-import packages lazy 6659902a731767b3405d68e515c8edcc3af81119 caused a lot of importing a lot of things in __init__ which makes loading anything, say session, really slow. The load time for keystoneclient is really critical since every client uses it. And having a CLI take several seconds to do nothing is really bad user experience. This drops the hot cache import time of keystoneclient.session down to 160ms which is about 60ms faster (down from 220ms without this patch) for me. Change-Id: I917503ae54c9abcff417f0a0368abb765a847b6e Partial-Bug: #1431649 Co-Authored-By: Robert Collins --- keystoneclient/__init__.py | 39 +++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/keystoneclient/__init__.py b/keystoneclient/__init__.py index 08545c573..96f32ab71 100644 --- a/keystoneclient/__init__.py +++ b/keystoneclient/__init__.py @@ -27,18 +27,10 @@ Identity V2 and V3 clients can also be created directly. See """ +import sys import pbr.version -from keystoneclient import access -from keystoneclient import client -from keystoneclient import exceptions -from keystoneclient import generic -from keystoneclient import httpclient -from keystoneclient import service_catalog -from keystoneclient import v2_0 -from keystoneclient import v3 - __version__ = pbr.version.VersionInfo('python-keystoneclient').version_string() @@ -55,3 +47,32 @@ __all__ = [ 'httpclient', 'service_catalog', ] + + +class _LazyImporter(object): + def __init__(self, module): + self._module = module + + def __getattr__(self, name): + # NB: this is only called until the import has been done. + # These submodules are part of the API without explicit importing, but + # expensive to load, so we load them on-demand rather than up-front. + lazy_submodules = [ + 'access', + 'client', + 'exceptions', + 'generic', + 'httpclient', + 'service_catalog', + 'v2_0', + 'v3', + ] + # __import__ rather than importlib for Python 2.6. + if name in lazy_submodules: + __import__('keystoneclient.%s' % name) + return getattr(self, name) + # Return module attributes like __all__ etc. + return getattr(self._module, name) + + +sys.modules[__name__] = _LazyImporter(sys.modules[__name__])