From ecf87ad513fd8af6e4a6093ed918723a7d88d5ca Mon Sep 17 00:00:00 2001 From: yujin <891837834@qq.com> Date: Tue, 31 Aug 2021 16:14:04 +0800 Subject: [PATCH] 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. --- django/utils/module_loading.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py index 8c798f69bb..1df82b1c32 100644 --- a/django/utils/module_loading.py +++ b/django/utils/module_loading.py @@ -1,9 +1,17 @@ import copy import os +import sys from importlib import import_module 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): """ 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: raise ImportError("%s doesn't look like a module path" % dotted_path) from err - module = import_module(module_path) - try: - return getattr(module, class_name) + return cached_import(module_path, class_name) except AttributeError as err: raise ImportError('Module "%s" does not define a "%s" attribute/class' % ( module_path, class_name)