diff -r c511ee30fd3d Python/_warnings.c --- a/Python/_warnings.c Sat Mar 19 10:36:36 2016 +0100 +++ b/Python/_warnings.c Sat Mar 19 14:33:32 2016 +0100 @@ -40,11 +40,11 @@ check_matched(PyObject *obj, PyObject *a A NULL return value can mean false or an error. */ static PyObject * -get_warnings_attr(const char *attr) +get_warnings_attr(const char *attr, int try_import) { static PyObject *warnings_str = NULL; PyObject *all_modules; - PyObject *warnings_module; + PyObject *warnings_module, *obj; int result; if (warnings_str == NULL) { @@ -53,15 +53,30 @@ get_warnings_attr(const char *attr) return NULL; } - all_modules = PyImport_GetModuleDict(); - result = PyDict_Contains(all_modules, warnings_str); - if (result == -1 || result == 0) + /* don't try to import after Python finallization has started */ + if (try_import && _Py_Finalizing == NULL) { + warnings_module = PyImport_Import(warnings_str); + if (warnings_module == NULL) + return NULL; + } + else { + all_modules = PyImport_GetModuleDict(); + result = PyDict_Contains(all_modules, warnings_str); + if (result == -1 || result == 0) + return NULL; + + warnings_module = PyDict_GetItem(all_modules, warnings_str); + Py_INCREF(warnings_module); + } + + if (!PyObject_HasAttrString(warnings_module, attr)) { + Py_DECREF(warnings_module); return NULL; + } - warnings_module = PyDict_GetItem(all_modules, warnings_str); - if (!PyObject_HasAttrString(warnings_module, attr)) - return NULL; - return PyObject_GetAttrString(warnings_module, attr); + obj = PyObject_GetAttrString(warnings_module, attr); + Py_DECREF(warnings_module); + return obj; } @@ -70,7 +85,7 @@ get_once_registry(void) { PyObject *registry; - registry = get_warnings_attr("onceregistry"); + registry = get_warnings_attr("onceregistry", 0); if (registry == NULL) { if (PyErr_Occurred()) return NULL; @@ -87,7 +102,7 @@ get_default_action(void) { PyObject *default_action; - default_action = get_warnings_attr("defaultaction"); + default_action = get_warnings_attr("defaultaction", 0); if (default_action == NULL) { if (PyErr_Occurred()) { return NULL; @@ -110,7 +125,7 @@ get_filter(PyObject *category, PyObject Py_ssize_t i; PyObject *warnings_filters; - warnings_filters = get_warnings_attr("filters"); + warnings_filters = get_warnings_attr("filters", 0); if (warnings_filters == NULL) { if (PyErr_Occurred()) return NULL; @@ -366,7 +381,8 @@ call_show_warning(PyObject *category, Py { PyObject *show_fn, *msg, *res, *warnmsg_cls = NULL; - show_fn = get_warnings_attr("_showwarnmsg"); + /* Only try to import warnings if source is set */ + show_fn = get_warnings_attr("_showwarnmsg", source != NULL); if (show_fn == NULL) { if (PyErr_Occurred()) return -1; @@ -380,7 +396,7 @@ call_show_warning(PyObject *category, Py goto error; } - warnmsg_cls = get_warnings_attr("WarningMessage"); + warnmsg_cls = get_warnings_attr("WarningMessage", 0); if (warnmsg_cls == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get warnings.WarningMessage");