[Python-checkins] bpo-42260: Initialize time and warnings earlier at startup (GH-23249)

vstinner webhook-mailer at python.org
Thu Nov 12 09:14:17 EST 2020


https://github.com/python/cpython/commit/ef75a625cdf8377d687a04948b4db9bc1917bf19
commit: ef75a625cdf8377d687a04948b4db9bc1917bf19
branch: master
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2020-11-12T15:14:13+01:00
summary:

bpo-42260: Initialize time and warnings earlier at startup (GH-23249)

* Call _PyTime_Init() and _PyWarnings_InitState() earlier during the
  Python initialization.
* Inline _PyImportHooks_Init() into _PySys_InitCore().
* The _warnings initialization function no longer call
  _PyWarnings_InitState() to prevent resetting filters_version to 0.
* _PyWarnings_InitState() now returns an int and no longer clear the
  state in case of error (it's done anyway at Python exit).
* Rework init_importlib(), fix refleaks on errors.

files:
M Include/internal/pycore_interp.h
M Include/internal/pycore_pylifecycle.h
M Include/internal/pycore_warnings.h
M Python/_warnings.c
M Python/import.c
M Python/pylifecycle.c
M Python/sysmodule.c

diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index 4b67a86a25a79..184878ce14603 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -190,10 +190,14 @@ struct _is {
     struct _ceval_state ceval;
     struct _gc_runtime_state gc;
 
+    // sys.modules dictionary
     PyObject *modules;
     PyObject *modules_by_index;
+    // Dictionary of the sys module
     PyObject *sysdict;
+    // Dictionary of the builtins module
     PyObject *builtins;
+    // importlib module
     PyObject *importlib;
 
     /* Used in Modules/_threadmodule.c. */
@@ -218,7 +222,7 @@ struct _is {
 
     PyObject *builtins_copy;
     PyObject *import_func;
-    /* Initialized to PyEval_EvalFrameDefault(). */
+    // Initialized to _PyEval_EvalFrameDefault().
     _PyFrameEvalFunction eval_frame;
 
     Py_ssize_t co_extra_user_count;
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index 606252b968da9..e748112cbf7fe 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -48,7 +48,6 @@ extern int _PySys_UpdateConfig(PyThreadState *tstate);
 extern PyStatus _PyExc_Init(PyThreadState *tstate);
 extern PyStatus _PyErr_Init(void);
 extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
-extern PyStatus _PyImportHooks_Init(PyThreadState *tstate);
 extern int _PyFloat_Init(void);
 extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
 
diff --git a/Include/internal/pycore_warnings.h b/Include/internal/pycore_warnings.h
index cafe305edb0e0..2a473b860c47d 100644
--- a/Include/internal/pycore_warnings.h
+++ b/Include/internal/pycore_warnings.h
@@ -17,7 +17,7 @@ struct _warnings_runtime_state {
     long filters_version;
 };
 
-extern PyStatus _PyWarnings_InitState(PyThreadState *tstate);
+extern int _PyWarnings_InitState(PyThreadState *tstate);
 
 #ifdef __cplusplus
 }
diff --git a/Python/_warnings.c b/Python/_warnings.c
index e42b7c3be3db9..8d33fbe0f878b 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -114,37 +114,34 @@ init_filters(void)
 }
 
 /* Initialize the given warnings module state. */
-static int
-warnings_init_state(WarningsState *st)
+int
+_PyWarnings_InitState(PyThreadState *tstate)
 {
+    WarningsState *st = &tstate->interp->warnings;
+
     if (st->filters == NULL) {
         st->filters = init_filters();
         if (st->filters == NULL) {
-            goto error;
+            return -1;
         }
     }
 
     if (st->once_registry == NULL) {
         st->once_registry = PyDict_New();
         if (st->once_registry == NULL) {
-            goto error;
+            return -1;
         }
     }
 
     if (st->default_action == NULL) {
         st->default_action = PyUnicode_FromString("default");
         if (st->default_action == NULL) {
-            goto error;
+            return -1;
         }
     }
 
     st->filters_version = 0;
-
     return 0;
-
-error:
-    warnings_clear_state(st);
-    return -1;
 }
 
 
@@ -1367,16 +1364,6 @@ static struct PyModuleDef warningsmodule = {
 };
 
 
-PyStatus
-_PyWarnings_InitState(PyThreadState *tstate)
-{
-    if (warnings_init_state(&tstate->interp->warnings) < 0) {
-        return _PyStatus_ERR("can't initialize warnings");
-    }
-    return _PyStatus_OK();
-}
-
-
 PyMODINIT_FUNC
 _PyWarnings_Init(void)
 {
@@ -1391,9 +1378,6 @@ _PyWarnings_Init(void)
     if (st == NULL) {
         goto error;
     }
-    if (warnings_init_state(st) < 0) {
-        goto error;
-    }
 
     if (PyModule_AddObjectRef(m, "filters", st->filters) < 0) {
         goto error;
diff --git a/Python/import.c b/Python/import.c
index 77e6baef011e3..51630c3486af6 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -51,43 +51,6 @@ module _imp
 
 /* Initialize things */
 
-PyStatus
-_PyImportHooks_Init(PyThreadState *tstate)
-{
-    PyObject *v, *path_hooks = NULL;
-    int err = 0;
-
-    /* adding sys.path_hooks and sys.path_importer_cache */
-    v = PyList_New(0);
-    if (v == NULL)
-        goto error;
-    err = PySys_SetObject("meta_path", v);
-    Py_DECREF(v);
-    if (err)
-        goto error;
-    v = PyDict_New();
-    if (v == NULL)
-        goto error;
-    err = PySys_SetObject("path_importer_cache", v);
-    Py_DECREF(v);
-    if (err)
-        goto error;
-    path_hooks = PyList_New(0);
-    if (path_hooks == NULL)
-        goto error;
-    err = PySys_SetObject("path_hooks", path_hooks);
-    if (err) {
-        goto error;
-    }
-    Py_DECREF(path_hooks);
-    return _PyStatus_OK();
-
-  error:
-    _PyErr_Print(tstate);
-    return _PyStatus_ERR("initializing sys.meta_path, sys.path_hooks, "
-                        "or path_importer_cache failed");
-}
-
 PyStatus
 _PyImportZip_Init(PyThreadState *tstate)
 {
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 93bce49b63d27..2d43e016efd50 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -135,59 +135,61 @@ Py_IsInitialized(void)
    having the lock, but you cannot use multiple threads.)
 
 */
-
-static PyStatus
+static int
 init_importlib(PyThreadState *tstate, PyObject *sysmod)
 {
-    PyObject *importlib;
-    PyObject *impmod;
-    PyObject *value;
+    assert(!_PyErr_Occurred(tstate));
+
     PyInterpreterState *interp = tstate->interp;
     int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
 
-    /* Import _importlib through its frozen version, _frozen_importlib. */
-    if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
-        return _PyStatus_ERR("can't import _frozen_importlib");
-    }
-    else if (verbose) {
+    // Import _importlib through its frozen version, _frozen_importlib.
+    if (verbose) {
         PySys_FormatStderr("import _frozen_importlib # frozen\n");
     }
-    importlib = PyImport_AddModule("_frozen_importlib");
+    if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
+        return -1;
+    }
+    PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
     if (importlib == NULL) {
-        return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules");
+        return -1;
     }
-    interp->importlib = importlib;
-    Py_INCREF(interp->importlib);
-
-    interp->import_func = _PyDict_GetItemStringWithError(interp->builtins, "__import__");
-    if (interp->import_func == NULL)
-        return _PyStatus_ERR("__import__ not found");
-    Py_INCREF(interp->import_func);
+    interp->importlib = Py_NewRef(importlib);
 
-    /* Import the _imp module */
-    impmod = PyInit__imp();
-    if (impmod == NULL) {
-        return _PyStatus_ERR("can't import _imp");
+    PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,
+                                                           "__import__");
+    if (import_func == NULL) {
+        return -1;
     }
-    else if (verbose) {
+    interp->import_func = Py_NewRef(import_func);
+
+    // Import the _imp module
+    if (verbose) {
         PySys_FormatStderr("import _imp # builtin\n");
     }
-    if (_PyImport_SetModuleString("_imp", impmod) < 0) {
-        return _PyStatus_ERR("can't save _imp to sys.modules");
+    PyObject *imp_mod = PyInit__imp();
+    if (imp_mod == NULL) {
+        return -1;
+    }
+    if (_PyImport_SetModuleString("_imp", imp_mod) < 0) {
+        Py_DECREF(imp_mod);
+        return -1;
     }
 
-    /* Install importlib as the implementation of import */
-    value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
+    // Install importlib as the implementation of import
+    PyObject *value = PyObject_CallMethod(importlib, "_install",
+                                          "OO", sysmod, imp_mod);
+    Py_DECREF(imp_mod);
     if (value == NULL) {
-        _PyErr_Print(tstate);
-        return _PyStatus_ERR("importlib install failed");
+        return -1;
     }
     Py_DECREF(value);
-    Py_DECREF(impmod);
 
-    return _PyStatus_OK();
+    assert(!_PyErr_Occurred(tstate));
+    return 0;
 }
 
+
 static PyStatus
 init_importlib_external(PyThreadState *tstate)
 {
@@ -700,6 +702,9 @@ pycore_init_types(PyThreadState *tstate)
         }
     }
 
+    if (_PyWarnings_InitState(tstate) < 0) {
+        return _PyStatus_ERR("can't initialize warnings");
+    }
     return _PyStatus_OK();
 }
 
@@ -747,37 +752,6 @@ pycore_init_builtins(PyThreadState *tstate)
 }
 
 
-static PyStatus
-pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
-{
-    assert(!_PyErr_Occurred(tstate));
-
-    PyStatus status = _PyImportHooks_Init(tstate);
-    if (_PyStatus_EXCEPTION(status)) {
-        return status;
-    }
-
-    /* Initialize _warnings. */
-    status = _PyWarnings_InitState(tstate);
-    if (_PyStatus_EXCEPTION(status)) {
-        return status;
-    }
-
-    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
-    if (config->_install_importlib) {
-        /* This call sets up builtin and frozen import support */
-        status = init_importlib(tstate, sysmod);
-        if (_PyStatus_EXCEPTION(status)) {
-            return status;
-        }
-    }
-
-    assert(!_PyErr_Occurred(tstate));
-
-    return _PyStatus_OK();
-}
-
-
 static PyStatus
 pycore_interp_init(PyThreadState *tstate)
 {
@@ -789,6 +763,12 @@ pycore_interp_init(PyThreadState *tstate)
         goto done;
     }
 
+    if (_Py_IsMainInterpreter(tstate)) {
+        if (_PyTime_Init() < 0) {
+            return _PyStatus_ERR("can't initialize time");
+        }
+    }
+
     status = _PySys_Create(tstate, &sysmod);
     if (_PyStatus_EXCEPTION(status)) {
         goto done;
@@ -799,7 +779,13 @@ pycore_interp_init(PyThreadState *tstate)
         goto done;
     }
 
-    status = pycore_init_import_warnings(tstate, sysmod);
+    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
+    if (config->_install_importlib) {
+        /* This call sets up builtin and frozen import support */
+        if (init_importlib(tstate, sysmod) < 0) {
+            return _PyStatus_ERR("failed to initialize importlib");
+        }
+    }
 
 done:
     /* sys.modules['sys'] contains a strong reference to the module */
@@ -1044,12 +1030,6 @@ init_interp_main(PyThreadState *tstate)
         return status;
     }
 
-    if (is_main_interp) {
-        if (_PyTime_Init() < 0) {
-            return _PyStatus_ERR("can't initialize time");
-        }
-    }
-
     if (interpreter_update_config(tstate, 1) < 0) {
         return _PyStatus_ERR("failed to update the Python config");
     }
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 61741f7432d34..f05b33a9aacf1 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -2841,6 +2841,11 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
         }
     }
 
+    /* adding sys.path_hooks and sys.path_importer_cache */
+    SET_SYS("meta_path", PyList_New(0));
+    SET_SYS("path_importer_cache", PyDict_New());
+    SET_SYS("path_hooks", PyList_New(0));
+
     if (_PyErr_Occurred(tstate)) {
         goto err_occurred;
     }



More information about the Python-checkins mailing list