bpo-36829: Add sys.unraisablehook() (GH-13187)

Add new sys.unraisablehook() function which can be overridden to
control how "unraisable exceptions" are handled. It is called when an
exception has occurred but there is no way for Python to handle it.
For example, when a destructor raises an exception or during garbage
collection (gc.collect()).

Changes:

* Add an internal UnraisableHookArgs type used to pass arguments to
  sys.unraisablehook.
* Add _PyErr_WriteUnraisableDefaultHook().
* The default hook now ignores exception on writing the traceback.
* test_sys now uses unittest.main() to automatically discover tests:
  remove test_main().
* Add _PyErr_Init().
* Fix PyErr_WriteUnraisable(): hold a strong reference to sys.stderr
  while using it
This commit is contained in:
Victor Stinner 2019-05-22 11:28:22 +02:00 committed by GitHub
parent 2725cb01d7
commit ef9d9b6312
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 497 additions and 123 deletions

View File

@ -72,6 +72,9 @@ Printing and clearing
.. c:function:: void PyErr_WriteUnraisable(PyObject *obj)
Call :func:`sys.unraisablehook` using the current exception and *obj*
argument.
This utility function prints a warning message to ``sys.stderr`` when an
exception has been set but it is impossible for the interpreter to actually
raise the exception. It is used, for example, when an exception occurs in an
@ -81,6 +84,8 @@ Printing and clearing
in which the unraisable exception occurred. If possible,
the repr of *obj* will be printed in the warning message.
An exception must be set when calling this function.
Raising exceptions
==================

View File

@ -248,16 +248,19 @@ always available.
before the program exits. The handling of such top-level exceptions can be
customized by assigning another three-argument function to ``sys.excepthook``.
See also :func:`unraisablehook` which handles unraisable exceptions.
.. data:: __breakpointhook__
__displayhook__
__excepthook__
__unraisablehook__
These objects contain the original values of ``breakpointhook``,
``displayhook``, and ``excepthook`` at the start of the program. They are
saved so that ``breakpointhook``, ``displayhook`` and ``excepthook`` can be
restored in case they happen to get replaced with broken or alternative
objects.
``displayhook``, ``excepthook``, and ``unraisablehook`` at the start of the
program. They are saved so that ``breakpointhook``, ``displayhook`` and
``excepthook``, ``unraisablehook`` can be restored in case they happen to
get replaced with broken or alternative objects.
.. versionadded:: 3.7
__breakpointhook__
@ -1487,6 +1490,28 @@ always available.
is suppressed and only the exception type and value are printed.
.. function:: unraisablehook(unraisable, /)
Handle an unraisable exception.
Called when an exception has occurred but there is no way for Python to
handle it. For example, when a destructor raises an exception or during
garbage collection (:func:`gc.collect`).
The *unraisable* argument has the following attributes:
* *exc_type*: Exception type.
* *exc_value*: Exception value, can be ``None``.
* *exc_traceback*: Exception traceback, can be ``None``.
* *object*: Object causing the exception, can be ``None``.
:func:`sys.unraisablehook` can be overridden to control how unraisable
exceptions are handled.
See also :func:`excepthook` which handles uncaught exceptions.
.. versionadded:: 3.8
.. data:: version
A string containing the version number of the Python interpreter plus additional

View File

@ -481,6 +481,16 @@ and manipulating normal distributions of a random variable.
[7.672102882379219, 12.000027119750287, 4.647488369766392]
sys
---
Add new :func:`sys.unraisablehook` function which can be overridden to control
how "unraisable exceptions" are handled. It is called when an exception has
occurred but there is no way for Python to handle it. For example, when a
destructor raises an exception or during garbage collection
(:func:`gc.collect`).
tarfile
-------

View File

@ -48,6 +48,7 @@ extern int _PySys_InitMain(
PyInterpreterState *interp);
extern _PyInitError _PyImport_Init(PyInterpreterState *interp);
extern _PyInitError _PyExc_Init(void);
extern _PyInitError _PyErr_Init(void);
extern _PyInitError _PyBuiltins_AddExceptions(PyObject * bltinmod);
extern _PyInitError _PyImportHooks_Init(void);
extern int _PyFloat_Init(void);
@ -100,8 +101,11 @@ PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig(
const _PyCoreConfig *coreconfig,
const _PyArgv *args);
PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p);
PyAPI_FUNC(PyObject*) _PyErr_WriteUnraisableDefaultHook(PyObject *unraisable);
#ifdef __cplusplus
}
#endif

View File

@ -876,6 +876,81 @@ class SysModuleTest(unittest.TestCase):
self.assertEqual(out, 'mbcs replace')
@test.support.cpython_only
class UnraisableHookTest(unittest.TestCase):
def write_unraisable_exc(self, exc, obj):
import _testcapi
import types
try:
# raise the exception to get a traceback in the except block
try:
raise exc
except Exception as exc2:
_testcapi.write_unraisable_exc(exc2, obj)
return types.SimpleNamespace(exc_type=type(exc2),
exc_value=exc2,
exc_traceback=exc2.__traceback__,
object=obj)
finally:
# Explicitly break any reference cycle
exc = None
exc2 = None
def test_original_unraisablehook(self):
obj = "an object"
with test.support.captured_output("stderr") as stderr:
with test.support.swap_attr(sys, 'unraisablehook',
sys.__unraisablehook__):
self.write_unraisable_exc(ValueError(42), obj)
err = stderr.getvalue()
self.assertIn(f'Exception ignored in: {obj!r}\n', err)
self.assertIn('Traceback (most recent call last):\n', err)
self.assertIn('ValueError: 42\n', err)
def test_original_unraisablehook_wrong_type(self):
exc = ValueError(42)
with test.support.swap_attr(sys, 'unraisablehook',
sys.__unraisablehook__):
with self.assertRaises(TypeError):
sys.unraisablehook(exc)
def test_custom_unraisablehook(self):
hook_args = None
def hook_func(args):
nonlocal hook_args
hook_args = args
obj = object()
try:
with test.support.swap_attr(sys, 'unraisablehook', hook_func):
expected = self.write_unraisable_exc(ValueError(42), obj)
for attr in "exc_type exc_value exc_traceback object".split():
self.assertEqual(getattr(hook_args, attr),
getattr(expected, attr),
(hook_args, expected))
finally:
# expected and hook_args contain an exception: break reference cycle
expected = None
hook_args = None
def test_custom_unraisablehook_fail(self):
def hook_func(*args):
raise Exception("hook_func failed")
with test.support.captured_output("stderr") as stderr:
with test.support.swap_attr(sys, 'unraisablehook', hook_func):
self.write_unraisable_exc(ValueError(42), None)
err = stderr.getvalue()
self.assertIn(f'Exception ignored in: {hook_func!r}\n',
err)
self.assertIn('Traceback (most recent call last):\n', err)
self.assertIn('Exception: hook_func failed\n', err)
@test.support.cpython_only
class SizeofTest(unittest.TestCase):
@ -1277,8 +1352,5 @@ class SizeofTest(unittest.TestCase):
self.assertIsNone(cur.finalizer)
def test_main():
test.support.run_unittest(SysModuleTest, SizeofTest)
if __name__ == "__main__":
test_main()
unittest.main()

View File

@ -0,0 +1,5 @@
Add new :func:`sys.unraisablehook` function which can be overridden to
control how "unraisable exceptions" are handled. It is called when an
exception has occurred but there is no way for Python to handle it. For
example, when a destructor raises an exception or during garbage collection
(:func:`gc.collect`).

View File

@ -4982,6 +4982,20 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args))
#endif
static PyObject*
test_write_unraisable_exc(PyObject *self, PyObject *args)
{
PyObject *exc, *obj;
if (!PyArg_ParseTuple(args, "OO", &exc, &obj)) {
return NULL;
}
PyErr_SetObject((PyObject *)Py_TYPE(exc), exc);
PyErr_WriteUnraisable(obj);
Py_RETURN_NONE;
}
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
@ -5221,6 +5235,7 @@ static PyMethodDef TestMethods[] = {
#ifdef Py_REF_DEBUG
{"negative_refcount", negative_refcount, METH_NOARGS},
#endif
{"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS},
{NULL, NULL} /* sentinel */
};

View File

@ -65,6 +65,22 @@ sys_exc_info(PyObject *module, PyObject *Py_UNUSED(ignored))
return sys_exc_info_impl(module);
}
PyDoc_STRVAR(sys_unraisablehook__doc__,
"unraisablehook($module, unraisable, /)\n"
"--\n"
"\n"
"Handle an unraisable exception.\n"
"\n"
"The unraisable argument has the following attributes:\n"
"\n"
"* exc_type: Exception type.\n"
"* exc_value: Exception value.\n"
"* exc_tb: Exception traceback, can be None.\n"
"* obj: Object causing the exception, can be None.");
#define SYS_UNRAISABLEHOOK_METHODDEF \
{"unraisablehook", (PyCFunction)sys_unraisablehook, METH_O, sys_unraisablehook__doc__},
PyDoc_STRVAR(sys_exit__doc__,
"exit($module, status=None, /)\n"
"--\n"
@ -1060,4 +1076,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
#define SYS_GETANDROIDAPILEVEL_METHODDEF
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
/*[clinic end generated code: output=3ba4c194d00f1866 input=a9049054013a1b77]*/
/*[clinic end generated code: output=603e4d5a453dc769 input=a9049054013a1b77]*/

View File

@ -2,6 +2,7 @@
/* Error handling */
#include "Python.h"
#include "pycore_coreconfig.h"
#include "pycore_pystate.h"
#ifndef __STDC__
@ -944,90 +945,271 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc,
}
/* Call when an exception has occurred but there is no way for Python
to handle it. Examples: exception in __del__ or during GC. */
void
PyErr_WriteUnraisable(PyObject *obj)
PyDoc_STRVAR(UnraisableHookArgs__doc__,
"UnraisableHookArgs\n\
\n\
Type used to pass arguments to sys.unraisablehook.");
static PyTypeObject UnraisableHookArgsType;
static PyStructSequence_Field UnraisableHookArgs_fields[] = {
{"exc_type", "Exception type"},
{"exc_value", "Exception value"},
{"exc_traceback", "Exception traceback"},
{"object", "Object causing the exception"},
{0}
};
static PyStructSequence_Desc UnraisableHookArgs_desc = {
.name = "UnraisableHookArgs",
.doc = UnraisableHookArgs__doc__,
.fields = UnraisableHookArgs_fields,
.n_in_sequence = 4
};
_PyInitError
_PyErr_Init(void)
{
_Py_IDENTIFIER(__module__);
PyObject *f, *t, *v, *tb;
PyObject *moduleName = NULL;
const char *className;
PyErr_Fetch(&t, &v, &tb);
f = _PySys_GetObjectId(&PyId_stderr);
if (f == NULL || f == Py_None)
goto done;
if (obj) {
if (PyFile_WriteString("Exception ignored in: ", f) < 0)
goto done;
if (PyFile_WriteObject(obj, f, 0) < 0) {
PyErr_Clear();
if (PyFile_WriteString("<object repr() failed>", f) < 0) {
goto done;
}
if (UnraisableHookArgsType.tp_name == NULL) {
if (PyStructSequence_InitType2(&UnraisableHookArgsType,
&UnraisableHookArgs_desc) < 0) {
return _Py_INIT_ERR("failed to initialize UnraisableHookArgs type");
}
if (PyFile_WriteString("\n", f) < 0)
goto done;
}
return _Py_INIT_OK();
}
static PyObject *
make_unraisable_hook_args(PyObject *exc_type, PyObject *exc_value,
PyObject *exc_tb, PyObject *obj)
{
PyObject *args = PyStructSequence_New(&UnraisableHookArgsType);
if (args == NULL) {
return NULL;
}
if (PyTraceBack_Print(tb, f) < 0)
goto done;
Py_ssize_t pos = 0;
#define ADD_ITEM(exc_type) \
do { \
if (exc_type == NULL) { \
exc_type = Py_None; \
} \
Py_INCREF(exc_type); \
PyStructSequence_SET_ITEM(args, pos++, exc_type); \
} while (0)
if (!t)
goto done;
assert(PyExceptionClass_Check(t));
className = PyExceptionClass_Name(t);
ADD_ITEM(exc_type);
ADD_ITEM(exc_value);
ADD_ITEM(exc_tb);
ADD_ITEM(obj);
#undef ADD_ITEM
if (PyErr_Occurred()) {
Py_DECREF(args);
return NULL;
}
return args;
}
/* Default implementation of sys.unraisablehook.
It can be called to log the exception of a custom sys.unraisablehook.
Do nothing if sys.stderr attribute doesn't exist or is set to None. */
static int
write_unraisable_exc_file(PyObject *exc_type, PyObject *exc_value,
PyObject *exc_tb, PyObject *obj, PyObject *file)
{
if (obj != NULL && obj != Py_None) {
if (PyFile_WriteString("Exception ignored in: ", file) < 0) {
return -1;
}
if (PyFile_WriteObject(obj, file, 0) < 0) {
PyErr_Clear();
if (PyFile_WriteString("<object repr() failed>", file) < 0) {
return -1;
}
}
if (PyFile_WriteString("\n", file) < 0) {
return -1;
}
}
if (exc_tb != NULL && exc_tb != Py_None) {
if (PyTraceBack_Print(exc_tb, file) < 0) {
/* continue even if writing the traceback failed */
PyErr_Clear();
}
}
if (!exc_type) {
return -1;
}
assert(PyExceptionClass_Check(exc_type));
const char *className = PyExceptionClass_Name(exc_type);
if (className != NULL) {
const char *dot = strrchr(className, '.');
if (dot != NULL)
className = dot+1;
}
moduleName = _PyObject_GetAttrId(t, &PyId___module__);
_Py_IDENTIFIER(__module__);
PyObject *moduleName = _PyObject_GetAttrId(exc_type, &PyId___module__);
if (moduleName == NULL || !PyUnicode_Check(moduleName)) {
Py_XDECREF(moduleName);
PyErr_Clear();
if (PyFile_WriteString("<unknown>", f) < 0)
goto done;
if (PyFile_WriteString("<unknown>", file) < 0) {
return -1;
}
}
else {
if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) {
if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0)
goto done;
if (PyFile_WriteString(".", f) < 0)
goto done;
if (PyFile_WriteObject(moduleName, file, Py_PRINT_RAW) < 0) {
Py_DECREF(moduleName);
return -1;
}
Py_DECREF(moduleName);
if (PyFile_WriteString(".", file) < 0) {
return -1;
}
}
else {
Py_DECREF(moduleName);
}
}
if (className == NULL) {
if (PyFile_WriteString("<unknown>", f) < 0)
goto done;
if (PyFile_WriteString("<unknown>", file) < 0) {
return -1;
}
}
else {
if (PyFile_WriteString(className, f) < 0)
goto done;
if (PyFile_WriteString(className, file) < 0) {
return -1;
}
}
if (v && v != Py_None) {
if (PyFile_WriteString(": ", f) < 0)
goto done;
if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) {
if (exc_value && exc_value != Py_None) {
if (PyFile_WriteString(": ", file) < 0) {
return -1;
}
if (PyFile_WriteObject(exc_value, file, Py_PRINT_RAW) < 0) {
PyErr_Clear();
if (PyFile_WriteString("<exception str() failed>", f) < 0) {
goto done;
if (PyFile_WriteString("<exception str() failed>", file) < 0) {
return -1;
}
}
}
if (PyFile_WriteString("\n", f) < 0)
goto done;
if (PyFile_WriteString("\n", file) < 0) {
return -1;
}
return 0;
}
static int
write_unraisable_exc(PyObject *exc_type, PyObject *exc_value,
PyObject *exc_tb, PyObject *obj)
{
PyObject *file = _PySys_GetObjectId(&PyId_stderr);
if (file == NULL || file == Py_None) {
return 0;
}
/* Hold a strong reference to ensure that sys.stderr doesn't go away
while we use it */
Py_INCREF(file);
int res = write_unraisable_exc_file(exc_type, exc_value, exc_tb,
obj, file);
Py_DECREF(file);
return res;
}
PyObject*
_PyErr_WriteUnraisableDefaultHook(PyObject *args)
{
if (Py_TYPE(args) != &UnraisableHookArgsType) {
PyErr_SetString(PyExc_TypeError,
"sys.unraisablehook argument type "
"must be UnraisableHookArgs");
return NULL;
}
/* Borrowed references */
PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
PyObject *obj = PyStructSequence_GET_ITEM(args, 3);
if (write_unraisable_exc(exc_type, exc_value, exc_tb, obj) < 0) {
return NULL;
}
Py_RETURN_NONE;
}
/* Call sys.unraisablehook().
This function can be used when an exception has occurred but there is no way
for Python to handle it. For example, when a destructor raises an exception
or during garbage collection (gc.collect()).
An exception must be set when calling this function. */
void
PyErr_WriteUnraisable(PyObject *obj)
{
PyObject *exc_type, *exc_value, *exc_tb;
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
assert(exc_type != NULL);
if (exc_type == NULL) {
/* sys.unraisablehook requires that at least exc_type is set */
goto default_hook;
}
_Py_IDENTIFIER(unraisablehook);
PyObject *hook = _PySys_GetObjectId(&PyId_unraisablehook);
if (hook != NULL && hook != Py_None) {
PyObject *hook_args;
hook_args = make_unraisable_hook_args(exc_type, exc_value, exc_tb, obj);
if (hook_args != NULL) {
PyObject *args[1] = {hook_args};
PyObject *res = _PyObject_FastCall(hook, args, 1);
Py_DECREF(hook_args);
if (res != NULL) {
Py_DECREF(res);
goto done;
}
}
/* sys.unraisablehook failed: log its error using default hook */
Py_XDECREF(exc_type);
Py_XDECREF(exc_value);
Py_XDECREF(exc_tb);
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
obj = hook;
}
default_hook:
/* Call the default unraisable hook (ignore failure) */
(void)write_unraisable_exc(exc_type, exc_value, exc_tb, obj);
done:
Py_XDECREF(moduleName);
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
Py_XDECREF(exc_type);
Py_XDECREF(exc_value);
Py_XDECREF(exc_tb);
PyErr_Clear(); /* Just in case */
}

120
Python/importlib.h generated
View File

@ -1326,8 +1326,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
97,114,100,108,101,115,115,32,111,102,32,97,110,121,32,114,
97,105,115,101,100,32,101,120,99,101,112,116,105,111,110,115,
46,78,41,2,114,57,0,0,0,114,60,0,0,0,41,4,
114,30,0,0,0,90,8,101,120,99,95,116,121,112,101,90,
9,101,120,99,95,118,97,108,117,101,90,13,101,120,99,95,
114,30,0,0,0,218,8,101,120,99,95,116,121,112,101,218,
9,101,120,99,95,118,97,108,117,101,218,13,101,120,99,95,
116,114,97,99,101,98,97,99,107,114,10,0,0,0,114,10,
0,0,0,114,11,0,0,0,114,56,0,0,0,99,3,0,
0,115,2,0,0,0,0,2,122,27,95,73,109,112,111,114,
@ -1358,7 +1358,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
98,97,115,101,114,10,0,0,0,114,10,0,0,0,114,11,
0,0,0,218,13,95,114,101,115,111,108,118,101,95,110,97,
109,101,104,3,0,0,115,10,0,0,0,0,2,16,1,12,
1,8,1,8,1,114,185,0,0,0,99,3,0,0,0,0,
1,8,1,8,1,114,188,0,0,0,99,3,0,0,0,0,
0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,
0,0,0,115,34,0,0,0,124,0,160,0,124,1,124,2,
161,2,125,3,124,3,100,0,107,8,114,24,100,0,83,0,
@ -1368,7 +1368,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
109,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,
0,0,0,218,17,95,102,105,110,100,95,115,112,101,99,95,
108,101,103,97,99,121,113,3,0,0,115,8,0,0,0,0,
3,12,1,8,1,4,1,114,187,0,0,0,99,3,0,0,
3,12,1,8,1,4,1,114,190,0,0,0,99,3,0,0,
0,0,0,0,0,0,0,0,0,10,0,0,0,10,0,0,
0,67,0,0,0,115,12,1,0,0,116,0,106,1,125,3,
124,3,100,1,107,8,114,22,116,2,100,2,131,1,130,1,
@ -1398,17 +1398,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
104,114,79,0,0,0,218,9,95,119,97,114,110,105,110,103,
115,218,4,119,97,114,110,218,13,73,109,112,111,114,116,87,
97,114,110,105,110,103,114,92,0,0,0,114,178,0,0,0,
114,166,0,0,0,114,106,0,0,0,114,187,0,0,0,114,
114,166,0,0,0,114,106,0,0,0,114,190,0,0,0,114,
105,0,0,0,41,10,114,17,0,0,0,114,164,0,0,0,
114,165,0,0,0,114,188,0,0,0,90,9,105,115,95,114,
101,108,111,97,100,114,186,0,0,0,114,166,0,0,0,114,
114,165,0,0,0,114,191,0,0,0,90,9,105,115,95,114,
101,108,111,97,100,114,189,0,0,0,114,166,0,0,0,114,
95,0,0,0,114,96,0,0,0,114,105,0,0,0,114,10,
0,0,0,114,10,0,0,0,114,11,0,0,0,218,10,95,
102,105,110,100,95,115,112,101,99,122,3,0,0,115,54,0,
0,0,0,2,6,1,8,2,8,3,4,1,12,5,10,1,
8,1,8,1,2,1,10,1,14,1,12,1,8,1,20,2,
22,1,8,2,18,1,10,1,2,1,10,1,14,4,14,2,
8,1,8,2,10,2,10,2,114,192,0,0,0,99,3,0,
8,1,8,2,10,2,10,2,114,195,0,0,0,99,3,0,
0,0,0,0,0,0,0,0,0,0,3,0,0,0,5,0,
0,0,67,0,0,0,115,108,0,0,0,116,0,124,0,116,
1,131,2,115,28,116,2,100,1,160,3,116,4,124,0,131,
@ -1432,12 +1432,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
121,32,109,111,100,117,108,101,32,110,97,109,101,78,41,7,
218,10,105,115,105,110,115,116,97,110,99,101,218,3,115,116,
114,218,9,84,121,112,101,69,114,114,111,114,114,45,0,0,
0,114,14,0,0,0,114,182,0,0,0,114,79,0,0,0,
169,3,114,17,0,0,0,114,183,0,0,0,114,184,0,0,
0,114,14,0,0,0,114,185,0,0,0,114,79,0,0,0,
169,3,114,17,0,0,0,114,186,0,0,0,114,187,0,0,
0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,
218,13,95,115,97,110,105,116,121,95,99,104,101,99,107,169,
3,0,0,115,22,0,0,0,0,2,10,1,18,1,8,1,
8,1,8,1,10,1,10,1,4,1,8,2,12,1,114,197,
8,1,8,1,10,1,10,1,4,1,8,2,12,1,114,200,
0,0,0,122,16,78,111,32,109,111,100,117,108,101,32,110,
97,109,101,100,32,122,4,123,33,114,125,99,2,0,0,0,
0,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0,
@ -1462,7 +1462,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
0,114,92,0,0,0,114,67,0,0,0,114,141,0,0,0,
114,106,0,0,0,218,8,95,69,82,82,95,77,83,71,114,
45,0,0,0,218,19,77,111,100,117,108,101,78,111,116,70,
111,117,110,100,69,114,114,111,114,114,192,0,0,0,114,159,
111,117,110,100,69,114,114,111,114,114,195,0,0,0,114,159,
0,0,0,114,5,0,0,0,41,8,114,17,0,0,0,218,
7,105,109,112,111,114,116,95,114,164,0,0,0,114,130,0,
0,0,90,13,112,97,114,101,110,116,95,109,111,100,117,108,
@ -1472,7 +1472,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
117,110,108,111,99,107,101,100,188,3,0,0,115,42,0,0,
0,0,1,4,1,14,1,4,1,10,1,10,2,10,1,10,
1,10,1,2,1,10,1,14,1,16,1,20,1,10,1,8,
1,20,2,8,1,4,2,10,1,22,1,114,202,0,0,0,
1,20,2,8,1,4,2,10,1,22,1,114,205,0,0,0,
99,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,
0,10,0,0,0,67,0,0,0,115,106,0,0,0,116,0,
124,0,131,1,143,50,1,0,116,1,106,2,160,3,124,0,
@ -1488,14 +1488,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
101,32,105,110,32,115,121,115,46,109,111,100,117,108,101,115,
114,16,0,0,0,41,9,114,50,0,0,0,114,15,0,0,
0,114,92,0,0,0,114,34,0,0,0,218,14,95,78,69,
69,68,83,95,76,79,65,68,73,78,71,114,202,0,0,0,
114,45,0,0,0,114,200,0,0,0,114,65,0,0,0,41,
4,114,17,0,0,0,114,201,0,0,0,114,96,0,0,0,
69,68,83,95,76,79,65,68,73,78,71,114,205,0,0,0,
114,45,0,0,0,114,203,0,0,0,114,65,0,0,0,41,
4,114,17,0,0,0,114,204,0,0,0,114,96,0,0,0,
114,75,0,0,0,114,10,0,0,0,114,10,0,0,0,114,
11,0,0,0,218,14,95,102,105,110,100,95,97,110,100,95,
108,111,97,100,218,3,0,0,115,22,0,0,0,0,2,10,
1,14,1,8,1,32,2,8,1,4,1,2,255,4,2,12,
2,8,1,114,204,0,0,0,114,22,0,0,0,99,3,0,
2,8,1,114,207,0,0,0,114,22,0,0,0,99,3,0,
0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0,
0,0,67,0,0,0,115,42,0,0,0,116,0,124,0,124,
1,124,2,131,3,1,0,124,2,100,1,107,4,114,32,116,
@ -1520,11 +1520,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
103,32,95,95,112,97,99,107,97,103,101,95,95,32,105,102,
10,32,32,32,32,116,104,101,32,108,111,97,100,101,114,32,
100,105,100,32,110,111,116,46,10,10,32,32,32,32,114,22,
0,0,0,41,4,114,197,0,0,0,114,185,0,0,0,114,
204,0,0,0,218,11,95,103,99,100,95,105,109,112,111,114,
116,114,196,0,0,0,114,10,0,0,0,114,10,0,0,0,
114,11,0,0,0,114,205,0,0,0,234,3,0,0,115,8,
0,0,0,0,9,12,1,8,1,12,1,114,205,0,0,0,
0,0,0,41,4,114,200,0,0,0,114,188,0,0,0,114,
207,0,0,0,218,11,95,103,99,100,95,105,109,112,111,114,
116,114,199,0,0,0,114,10,0,0,0,114,10,0,0,0,
114,11,0,0,0,114,208,0,0,0,234,3,0,0,115,8,
0,0,0,0,9,12,1,8,1,12,1,114,208,0,0,0,
169,1,218,9,114,101,99,117,114,115,105,118,101,99,3,0,
0,0,0,0,0,0,1,0,0,0,8,0,0,0,11,0,
0,0,67,0,0,0,115,226,0,0,0,124,1,68,0,93,
@ -1561,21 +1561,21 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
109,32,108,105,115,116,39,39,122,8,73,116,101,109,32,105,
110,32,122,18,32,109,117,115,116,32,98,101,32,115,116,114,
44,32,110,111,116,32,250,1,42,218,7,95,95,97,108,108,
95,95,84,114,206,0,0,0,114,179,0,0,0,78,41,16,
114,193,0,0,0,114,194,0,0,0,114,1,0,0,0,114,
195,0,0,0,114,14,0,0,0,114,4,0,0,0,218,16,
95,95,84,114,209,0,0,0,114,182,0,0,0,78,41,16,
114,196,0,0,0,114,197,0,0,0,114,1,0,0,0,114,
198,0,0,0,114,14,0,0,0,114,4,0,0,0,218,16,
95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116,
114,209,0,0,0,114,45,0,0,0,114,67,0,0,0,114,
200,0,0,0,114,17,0,0,0,114,15,0,0,0,114,92,
0,0,0,114,34,0,0,0,114,203,0,0,0,41,8,114,
96,0,0,0,218,8,102,114,111,109,108,105,115,116,114,201,
0,0,0,114,207,0,0,0,218,1,120,90,5,119,104,101,
114,212,0,0,0,114,45,0,0,0,114,67,0,0,0,114,
203,0,0,0,114,17,0,0,0,114,15,0,0,0,114,92,
0,0,0,114,34,0,0,0,114,206,0,0,0,41,8,114,
96,0,0,0,218,8,102,114,111,109,108,105,115,116,114,204,
0,0,0,114,210,0,0,0,218,1,120,90,5,119,104,101,
114,101,90,9,102,114,111,109,95,110,97,109,101,90,3,101,
120,99,114,10,0,0,0,114,10,0,0,0,114,11,0,0,
0,114,210,0,0,0,249,3,0,0,115,44,0,0,0,0,
0,114,213,0,0,0,249,3,0,0,115,44,0,0,0,0,
10,8,1,10,1,4,1,12,2,4,1,28,2,8,1,14,
1,10,1,2,255,8,2,10,1,14,1,2,1,14,1,16,
4,10,1,16,255,2,2,8,1,22,1,114,210,0,0,0,
4,10,1,16,255,2,2,8,1,22,1,114,213,0,0,0,
99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,
0,6,0,0,0,67,0,0,0,115,146,0,0,0,124,0,
160,0,100,1,161,1,125,1,124,0,160,0,100,2,161,1,
@ -1610,14 +1610,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
95,95,32,97,110,100,32,95,95,112,97,116,104,95,95,114,
1,0,0,0,114,141,0,0,0,114,128,0,0,0,114,22,
0,0,0,41,6,114,34,0,0,0,114,130,0,0,0,114,
189,0,0,0,114,190,0,0,0,114,191,0,0,0,114,129,
0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,183,
192,0,0,0,114,193,0,0,0,114,194,0,0,0,114,129,
0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,186,
0,0,0,114,95,0,0,0,114,10,0,0,0,114,10,0,
0,0,114,11,0,0,0,218,17,95,99,97,108,99,95,95,
95,112,97,99,107,97,103,101,95,95,30,4,0,0,115,38,
0,0,0,0,7,10,1,10,1,8,1,18,1,22,2,2,
0,2,254,6,3,4,1,8,1,6,2,6,2,2,0,2,
254,6,3,8,1,8,1,14,1,114,216,0,0,0,114,10,
254,6,3,8,1,8,1,14,1,114,219,0,0,0,114,10,
0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0,
9,0,0,0,5,0,0,0,67,0,0,0,115,180,0,0,
0,124,4,100,1,107,2,114,18,116,0,124,0,131,1,125,
@ -1662,18 +1662,18 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
96,32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,
108,101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,
32,32,32,114,22,0,0,0,78,114,128,0,0,0,114,141,
0,0,0,41,9,114,205,0,0,0,114,216,0,0,0,218,
9,112,97,114,116,105,116,105,111,110,114,181,0,0,0,114,
0,0,0,41,9,114,208,0,0,0,114,219,0,0,0,218,
9,112,97,114,116,105,116,105,111,110,114,184,0,0,0,114,
15,0,0,0,114,92,0,0,0,114,1,0,0,0,114,4,
0,0,0,114,210,0,0,0,41,9,114,17,0,0,0,114,
215,0,0,0,218,6,108,111,99,97,108,115,114,211,0,0,
0,114,184,0,0,0,114,96,0,0,0,90,8,103,108,111,
98,97,108,115,95,114,183,0,0,0,90,7,99,117,116,95,
0,0,0,114,213,0,0,0,41,9,114,17,0,0,0,114,
218,0,0,0,218,6,108,111,99,97,108,115,114,214,0,0,
0,114,187,0,0,0,114,96,0,0,0,90,8,103,108,111,
98,97,108,115,95,114,186,0,0,0,90,7,99,117,116,95,
111,102,102,114,10,0,0,0,114,10,0,0,0,114,11,0,
0,0,218,10,95,95,105,109,112,111,114,116,95,95,57,4,
0,0,115,30,0,0,0,0,11,8,1,10,2,16,1,8,
1,12,1,4,3,8,1,18,1,4,1,4,4,26,3,32,
1,10,1,12,2,114,219,0,0,0,99,1,0,0,0,0,
1,10,1,12,2,114,222,0,0,0,99,1,0,0,0,0,
0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,
0,0,0,115,38,0,0,0,116,0,160,1,124,0,161,1,
125,1,124,1,100,0,107,8,114,30,116,2,100,1,124,0,
@ -1685,7 +1685,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
0,0,0,114,10,0,0,0,114,11,0,0,0,218,18,95,
98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109,
101,94,4,0,0,115,8,0,0,0,0,1,10,1,8,1,
12,1,114,220,0,0,0,99,2,0,0,0,0,0,0,0,
12,1,114,223,0,0,0,99,2,0,0,0,0,0,0,0,
0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0,
115,166,0,0,0,124,1,97,0,124,0,97,1,116,2,116,
1,131,1,125,2,116,1,106,3,160,4,161,0,68,0,93,
@ -1714,12 +1714,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120,
112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32,
105,110,46,10,10,32,32,32,32,41,3,114,23,0,0,0,
114,189,0,0,0,114,64,0,0,0,78,41,15,114,57,0,
114,192,0,0,0,114,64,0,0,0,78,41,15,114,57,0,
0,0,114,15,0,0,0,114,14,0,0,0,114,92,0,0,
0,218,5,105,116,101,109,115,114,193,0,0,0,114,78,0,
0,218,5,105,116,101,109,115,114,196,0,0,0,114,78,0,
0,0,114,160,0,0,0,114,88,0,0,0,114,173,0,0,
0,114,142,0,0,0,114,148,0,0,0,114,1,0,0,0,
114,220,0,0,0,114,5,0,0,0,41,10,218,10,115,121,
114,223,0,0,0,114,5,0,0,0,41,10,218,10,115,121,
115,95,109,111,100,117,108,101,218,11,95,105,109,112,95,109,
111,100,117,108,101,90,11,109,111,100,117,108,101,95,116,121,
112,101,114,17,0,0,0,114,96,0,0,0,114,109,0,0,
@ -1730,7 +1730,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
218,6,95,115,101,116,117,112,101,4,0,0,115,36,0,0,
0,0,9,4,1,4,3,8,1,18,1,10,1,10,1,6,
1,10,1,6,2,2,1,10,1,12,3,10,1,8,1,10,
1,10,2,10,1,114,224,0,0,0,99,2,0,0,0,0,
1,10,2,10,1,114,227,0,0,0,99,2,0,0,0,0,
0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,
0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2,
1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1,
@ -1738,12 +1738,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116,
101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32,
97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108,
101,115,78,41,6,114,224,0,0,0,114,15,0,0,0,114,
188,0,0,0,114,120,0,0,0,114,160,0,0,0,114,173,
0,0,0,41,2,114,222,0,0,0,114,223,0,0,0,114,
101,115,78,41,6,114,227,0,0,0,114,15,0,0,0,114,
191,0,0,0,114,120,0,0,0,114,160,0,0,0,114,173,
0,0,0,41,2,114,225,0,0,0,114,226,0,0,0,114,
10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8,
95,105,110,115,116,97,108,108,136,4,0,0,115,6,0,0,
0,0,2,10,2,12,1,114,225,0,0,0,99,0,0,0,
0,0,2,10,2,12,1,114,228,0,0,0,99,0,0,0,
0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,
0,67,0,0,0,115,32,0,0,0,100,1,100,2,108,0,
125,0,124,0,97,1,124,0,160,2,116,3,106,4,116,5,
@ -1754,12 +1754,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
32,97,99,99,101,115,115,114,22,0,0,0,78,41,6,218,
26,95,102,114,111,122,101,110,95,105,109,112,111,114,116,108,
105,98,95,101,120,116,101,114,110,97,108,114,126,0,0,0,
114,225,0,0,0,114,15,0,0,0,114,92,0,0,0,114,
1,0,0,0,41,1,114,226,0,0,0,114,10,0,0,0,
114,228,0,0,0,114,15,0,0,0,114,92,0,0,0,114,
1,0,0,0,41,1,114,229,0,0,0,114,10,0,0,0,
114,10,0,0,0,114,11,0,0,0,218,27,95,105,110,115,
116,97,108,108,95,101,120,116,101,114,110,97,108,95,105,109,
112,111,114,116,101,114,115,144,4,0,0,115,6,0,0,0,
0,3,8,1,4,1,114,227,0,0,0,41,2,78,78,41,
0,3,8,1,4,1,114,230,0,0,0,41,2,78,78,41,
1,78,41,2,78,114,22,0,0,0,41,4,78,78,114,10,
0,0,0,114,22,0,0,0,41,50,114,3,0,0,0,114,
126,0,0,0,114,12,0,0,0,114,18,0,0,0,114,59,
@ -1771,13 +1771,13 @@ const unsigned char _Py_M__importlib_bootstrap[] = {
0,0,0,114,142,0,0,0,114,148,0,0,0,114,152,0,
0,0,114,107,0,0,0,114,93,0,0,0,114,158,0,0,
0,114,159,0,0,0,114,94,0,0,0,114,160,0,0,0,
114,173,0,0,0,114,178,0,0,0,114,185,0,0,0,114,
187,0,0,0,114,192,0,0,0,114,197,0,0,0,90,15,
114,173,0,0,0,114,178,0,0,0,114,188,0,0,0,114,
190,0,0,0,114,195,0,0,0,114,200,0,0,0,90,15,
95,69,82,82,95,77,83,71,95,80,82,69,70,73,88,114,
199,0,0,0,114,202,0,0,0,218,6,111,98,106,101,99,
116,114,203,0,0,0,114,204,0,0,0,114,205,0,0,0,
114,210,0,0,0,114,216,0,0,0,114,219,0,0,0,114,
220,0,0,0,114,224,0,0,0,114,225,0,0,0,114,227,
202,0,0,0,114,205,0,0,0,218,6,111,98,106,101,99,
116,114,206,0,0,0,114,207,0,0,0,114,208,0,0,0,
114,213,0,0,0,114,219,0,0,0,114,222,0,0,0,114,
223,0,0,0,114,227,0,0,0,114,228,0,0,0,114,230,
0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0,
0,0,114,11,0,0,0,218,8,60,109,111,100,117,108,101,
62,1,0,0,0,115,94,0,0,0,4,24,4,2,8,8,

View File

@ -587,6 +587,12 @@ pycore_init_types(void)
if (!_PyContext_Init()) {
return _Py_INIT_ERR("can't init context");
}
err = _PyErr_Init();
if (_Py_INIT_FAILED(err)) {
return err;
}
return _Py_INIT_OK();
}
@ -1462,6 +1468,12 @@ new_interpreter(PyThreadState **tstate_p)
return err;
}
err = _PyErr_Init();
if (_Py_INIT_FAILED(err)) {
return err;
}
/* XXX The following is lax in error checking */
PyObject *modules = PyDict_New();
if (modules == NULL) {

View File

@ -374,6 +374,30 @@ sys_exc_info_impl(PyObject *module)
}
/*[clinic input]
sys.unraisablehook
unraisable: object
/
Handle an unraisable exception.
The unraisable argument has the following attributes:
* exc_type: Exception type.
* exc_value: Exception value.
* exc_tb: Exception traceback, can be None.
* obj: Object causing the exception, can be None.
[clinic start generated code]*/
static PyObject *
sys_unraisablehook(PyObject *module, PyObject *unraisable)
/*[clinic end generated code: output=bb92838b32abaa14 input=fdbdb47fdd0bee06]*/
{
return _PyErr_WriteUnraisableDefaultHook(unraisable);
}
/*[clinic input]
sys.exit
@ -1672,6 +1696,7 @@ static PyMethodDef sys_methods[] = {
METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc},
SYS_GET_ASYNCGEN_HOOKS_METHODDEF
SYS_GETANDROIDAPILEVEL_METHODDEF
SYS_UNRAISABLEHOOK_METHODDEF
{NULL, NULL} /* sentinel */
};
@ -2369,6 +2394,9 @@ _PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp,
SET_SYS_FROM_STRING_BORROW(
"__breakpointhook__",
PyDict_GetItemString(sysdict, "breakpointhook"));
SET_SYS_FROM_STRING_BORROW("__unraisablehook__",
PyDict_GetItemString(sysdict, "unraisablehook"));
SET_SYS_FROM_STRING("version",
PyUnicode_FromString(Py_GetVersion()));
SET_SYS_FROM_STRING("hexversion",