Fixed #33099 -- Improved performance of import_string().

This improves performance of import_string() by avoiding multiple
imports for the same path.

Thanks Andrew Godwin and Keryn Knight for the implementation idea.
This commit is contained in:
yujin 2021-08-31 16:14:04 +08:00 committed by Mariusz Felisiak
parent ecf76cc1fb
commit ecf87ad513
1 changed files with 9 additions and 3 deletions

View File

@ -1,9 +1,17 @@
import copy import copy
import os import os
import sys
from importlib import import_module from importlib import import_module
from importlib.util import find_spec as importlib_find from importlib.util import find_spec as importlib_find
def cached_import(module_path, class_name):
modules = sys.modules
if module_path not in modules:
import_module(module_path)
return getattr(modules[module_path], class_name)
def import_string(dotted_path): def import_string(dotted_path):
""" """
Import a dotted module path and return the attribute/class designated by the Import a dotted module path and return the attribute/class designated by the
@ -14,10 +22,8 @@ def import_string(dotted_path):
except ValueError as err: except ValueError as err:
raise ImportError("%s doesn't look like a module path" % dotted_path) from err raise ImportError("%s doesn't look like a module path" % dotted_path) from err
module = import_module(module_path)
try: try:
return getattr(module, class_name) return cached_import(module_path, class_name)
except AttributeError as err: except AttributeError as err:
raise ImportError('Module "%s" does not define a "%s" attribute/class' % ( raise ImportError('Module "%s" does not define a "%s" attribute/class' % (
module_path, class_name) module_path, class_name)