@@ -4134,8 +4134,13 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
41344134 return final_mod ;
41354135}
41364136
4137+ // Add *name* to `sys.lazy_modules`.
4138+ // Skip the registration if *name* is already imported, and fully initialized.
4139+ // If *existing_mod_p* is not NULL, set it to the already imported object (or
4140+ // NULL if not found), for use by register_lazy_on_parent.
41374141static int
4138- lazy_modules_add (PyThreadState * tstate , PyObject * name )
4142+ lazy_modules_add (PyThreadState * tstate , PyObject * name ,
4143+ PyObject * * existing_mod_p )
41394144{
41404145 PyObject * mod = import_get_module (tstate , name );
41414146 if (mod == NULL && PyErr_Occurred ()) {
@@ -4161,7 +4166,12 @@ lazy_modules_add(PyThreadState *tstate, PyObject *name)
41614166 }
41624167 Py_XDECREF (spec );
41634168 }
4164- Py_XDECREF (mod );
4169+ if (existing_mod_p != NULL ) {
4170+ * existing_mod_p = mod ;
4171+ }
4172+ else {
4173+ Py_XDECREF (mod );
4174+ }
41654175 return loaded ? 0 : PySet_Add (LAZY_MODULES (tstate -> interp ), name );
41664176}
41674177
@@ -4226,30 +4236,25 @@ register_lazy_on_parent(PyThreadState *tstate, PyObject *name)
42264236}
42274237
42284238static int
4229- register_from_lazy_on_parent (PyThreadState * tstate , PyObject * abs_name ,
4230- PyObject * from )
4239+ register_from_lazy_on_parent (PyThreadState * tstate , PyObject * existing_module ,
4240+ PyObject * abs_name , PyObject * from )
42314241{
42324242 // IMPORT_FROM returns stored attributes directly. Their imports are
42334243 // already resolved or tracked by their own placeholders, so skip the alias.
4234- PyObject * mod = import_get_module (tstate , abs_name );
4235- if (mod == NULL && PyErr_Occurred ()) {
4236- return -1 ;
4237- }
42384244 int rc = 0 ;
4239- if (mod != NULL && PyModule_Check (mod )) {
4240- rc = PyDict_Contains (_PyModule_GetDict (mod ), from );
4241- }
4242- Py_XDECREF (mod );
4243- if (rc != 0 ) {
4244- return rc < 0 ? -1 : 0 ;
4245+ if (existing_module != NULL && PyModule_Check (existing_module )) {
4246+ rc = PyDict_Contains (_PyModule_GetDict (existing_module ), from );
4247+ if (rc != 0 ) {
4248+ return rc < 0 ? -1 : 0 ;
4249+ }
42454250 }
42464251
42474252 PyObject * fromname = PyUnicode_FromFormat ("%U.%U" , abs_name , from );
42484253 if (fromname == NULL ) {
42494254 return -1 ;
42504255 }
42514256
4252- rc = lazy_modules_add (tstate , fromname );
4257+ rc = lazy_modules_add (tstate , fromname , NULL );
42534258 if (rc == 0 ) {
42544259 rc = register_lazy_on_parent (tstate , fromname );
42554260 }
@@ -4341,6 +4346,8 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
43414346 }
43424347
43434348 PyObject * res = NULL ;
4349+ PyObject * existing_module = NULL ;
4350+
43444351 if (fromlist != NULL && PyUnicode_Check (fromlist )) {
43454352 fromlist = PyTuple_Pack (1 , fromlist );
43464353 if (fromlist == NULL ) {
@@ -4405,13 +4412,13 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
44054412 goto done ;
44064413 }
44074414
4408- if (lazy_modules_add (tstate , abs_name ) < 0 ) {
4415+ if (lazy_modules_add (tstate , abs_name , & existing_module ) < 0 ) {
44094416 goto error ;
44104417 }
44114418
44124419 if (PyTuple_Check (fromlist ) && PyTuple_GET_SIZE (fromlist )) {
44134420 for (Py_ssize_t i = 0 ; i < PyTuple_GET_SIZE (fromlist ); i ++ ) {
4414- if (register_from_lazy_on_parent (tstate , abs_name ,
4421+ if (register_from_lazy_on_parent (tstate , existing_module , abs_name ,
44154422 PyTuple_GET_ITEM (fromlist , i )) < 0 )
44164423 {
44174424 goto error ;
@@ -4428,6 +4435,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
44284435done :
44294436 Py_XDECREF (fromlist );
44304437 Py_DECREF (abs_name );
4438+ Py_XDECREF (existing_module );
44314439 return res ;
44324440}
44334441
0 commit comments