mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
Add sys.excepthook.
Update docstring and library reference section on 'sys' module. New API PyErr_Display, just for displaying errors, called by excepthook. Uncaught exceptions now call sys.excepthook; if that fails, we fall back to calling PyErr_Display directly. Also comes with sys.__excepthook__ and sys.__displayhook__.
This commit is contained in:
parent
37f7b38eb6
commit
b5c5132d1a
4 changed files with 108 additions and 23 deletions
|
@ -48,11 +48,32 @@ Availability: Windows.
|
||||||
If \var{value} is not \code{None}, this function prints it to
|
If \var{value} is not \code{None}, this function prints it to
|
||||||
\code{sys.stdout}, and saves it in \code{__builtin__._}.
|
\code{sys.stdout}, and saves it in \code{__builtin__._}.
|
||||||
|
|
||||||
This function is called when an expression is entered at the prompt
|
\code{sys.displayhook} is called on the result of evaluating
|
||||||
of an interactive Python session. It exists mainly so it can be
|
an expression entered in an interactive Python session.
|
||||||
overridden.
|
The display of these values can be customized by assigning
|
||||||
|
another function to \code{sys.displayhook}.
|
||||||
\end{funcdesc}
|
\end{funcdesc}
|
||||||
|
|
||||||
|
\begin{funcdesc}{excepthook}{\var{type}, \var{value}, \var{traceback}}
|
||||||
|
This function prints out a given traceback and exception to
|
||||||
|
\code{sys.stderr}.
|
||||||
|
|
||||||
|
\code{sys.excepthook} is called when an exception is raised
|
||||||
|
and uncaught. In an interactive session this happens just before
|
||||||
|
control is returned to the prompt; in a Python program this happens
|
||||||
|
just before the program exits.
|
||||||
|
The handling of such top-level exceptions can be customized by
|
||||||
|
assigning another function to \code{sys.excepthook}.
|
||||||
|
\end{funcdesc}
|
||||||
|
|
||||||
|
\begin{datadesc}{__displayhook__}
|
||||||
|
\dataline{__excepthook__}
|
||||||
|
These objects contain the original values of \code{displayhook}
|
||||||
|
and \code{excepthook} at the start of the program. They are saved
|
||||||
|
so that \code{displayhook} and \code{excepthook} can be restored
|
||||||
|
in case they happen to get replaced with broken objects.
|
||||||
|
\end{datadesc}
|
||||||
|
|
||||||
\begin{funcdesc}{exc_info}{}
|
\begin{funcdesc}{exc_info}{}
|
||||||
This function returns a tuple of three values that give information
|
This function returns a tuple of three values that give information
|
||||||
about the exception that is currently being handled. The information
|
about the exception that is currently being handled. The information
|
||||||
|
|
|
@ -59,6 +59,7 @@ DL_IMPORT(struct symtable *) Py_SymtableString(char *, char *, int);
|
||||||
|
|
||||||
DL_IMPORT(void) PyErr_Print(void);
|
DL_IMPORT(void) PyErr_Print(void);
|
||||||
DL_IMPORT(void) PyErr_PrintEx(int);
|
DL_IMPORT(void) PyErr_PrintEx(int);
|
||||||
|
DL_IMPORT(void) PyErr_Display(PyObject *, PyObject *, PyObject *);
|
||||||
|
|
||||||
DL_IMPORT(int) Py_AtExit(void (*func)(void));
|
DL_IMPORT(int) Py_AtExit(void (*func)(void));
|
||||||
|
|
||||||
|
|
|
@ -801,8 +801,7 @@ print_error_text(PyObject *f, int offset, char *text)
|
||||||
void
|
void
|
||||||
PyErr_PrintEx(int set_sys_last_vars)
|
PyErr_PrintEx(int set_sys_last_vars)
|
||||||
{
|
{
|
||||||
int err = 0;
|
PyObject *exception, *v, *tb, *hook;
|
||||||
PyObject *exception, *v, *tb, *f;
|
|
||||||
PyErr_Fetch(&exception, &v, &tb);
|
PyErr_Fetch(&exception, &v, &tb);
|
||||||
PyErr_NormalizeException(&exception, &v, &tb);
|
PyErr_NormalizeException(&exception, &v, &tb);
|
||||||
|
|
||||||
|
@ -845,14 +844,47 @@ PyErr_PrintEx(int set_sys_last_vars)
|
||||||
PySys_SetObject("last_value", v);
|
PySys_SetObject("last_value", v);
|
||||||
PySys_SetObject("last_traceback", tb);
|
PySys_SetObject("last_traceback", tb);
|
||||||
}
|
}
|
||||||
f = PySys_GetObject("stderr");
|
hook = PySys_GetObject("excepthook");
|
||||||
|
if (hook) {
|
||||||
|
PyObject *args = Py_BuildValue("(OOO)",
|
||||||
|
exception, v ? v : Py_None, tb ? tb : Py_None);
|
||||||
|
PyObject *result = PyEval_CallObject(hook, args);
|
||||||
|
if (result == NULL) {
|
||||||
|
PyObject *exception2, *v2, *tb2;
|
||||||
|
PyErr_Fetch(&exception2, &v2, &tb2);
|
||||||
|
PyErr_NormalizeException(&exception2, &v2, &tb2);
|
||||||
|
if (Py_FlushLine())
|
||||||
|
PyErr_Clear();
|
||||||
|
fflush(stdout);
|
||||||
|
PySys_WriteStderr("Error in sys.excepthook:\n");
|
||||||
|
PyErr_Display(exception2, v2, tb2);
|
||||||
|
PySys_WriteStderr("\nOriginal exception was:\n");
|
||||||
|
PyErr_Display(exception, v, tb);
|
||||||
|
}
|
||||||
|
Py_XDECREF(result);
|
||||||
|
Py_XDECREF(args);
|
||||||
|
} else {
|
||||||
|
PySys_WriteStderr("sys.excepthook is missing\n");
|
||||||
|
PyErr_Display(exception, v, tb);
|
||||||
|
}
|
||||||
|
Py_XDECREF(exception);
|
||||||
|
Py_XDECREF(v);
|
||||||
|
Py_XDECREF(tb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
PyObject *v = value;
|
||||||
|
PyObject *f = PySys_GetObject("stderr");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
fprintf(stderr, "lost sys.stderr\n");
|
fprintf(stderr, "lost sys.stderr\n");
|
||||||
else {
|
else {
|
||||||
if (Py_FlushLine())
|
if (Py_FlushLine())
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
err = PyTraceBack_Print(tb, f);
|
if (tb && tb != Py_None)
|
||||||
|
err = PyTraceBack_Print(tb, f);
|
||||||
if (err == 0 &&
|
if (err == 0 &&
|
||||||
PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError))
|
PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError))
|
||||||
{
|
{
|
||||||
|
@ -875,8 +907,6 @@ PyErr_PrintEx(int set_sys_last_vars)
|
||||||
PyFile_WriteString("\n", f);
|
PyFile_WriteString("\n", f);
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
print_error_text(f, offset, text);
|
print_error_text(f, offset, text);
|
||||||
Py_INCREF(message);
|
|
||||||
Py_DECREF(v);
|
|
||||||
v = message;
|
v = message;
|
||||||
/* Can't be bothered to check all those
|
/* Can't be bothered to check all those
|
||||||
PyFile_WriteString() calls */
|
PyFile_WriteString() calls */
|
||||||
|
@ -932,9 +962,6 @@ PyErr_PrintEx(int set_sys_last_vars)
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = PyFile_WriteString("\n", f);
|
err = PyFile_WriteString("\n", f);
|
||||||
}
|
}
|
||||||
Py_XDECREF(exception);
|
|
||||||
Py_XDECREF(v);
|
|
||||||
Py_XDECREF(tb);
|
|
||||||
/* If an error happened here, don't show it.
|
/* If an error happened here, don't show it.
|
||||||
XXX This is wrong, but too many callers rely on this behavior. */
|
XXX This is wrong, but too many callers rely on this behavior. */
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
|
|
|
@ -107,9 +107,25 @@ sys_displayhook(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char displayhook_doc[] =
|
static char displayhook_doc[] =
|
||||||
"displayhook(o) -> None\n"
|
"displayhook(object) -> None\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Print o to the stdout, and save it in __builtin__._\n";
|
"Print an object to sys.stdout and also save it in __builtin__._\n";
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
sys_excepthook(PyObject* self, PyObject* args)
|
||||||
|
{
|
||||||
|
PyObject *exc, *value, *tb;
|
||||||
|
if (!PyArg_ParseTuple(args, "OOO:excepthook", &exc, &value, &tb))
|
||||||
|
return NULL;
|
||||||
|
PyErr_Display(exc, value, tb);
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char excepthook_doc[] =
|
||||||
|
"excepthook(exctype, value, traceback) -> None\n"
|
||||||
|
"\n"
|
||||||
|
"Handle an exception by displaying it with a traceback on sys.stderr.\n";
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
sys_exc_info(PyObject *self, PyObject *args)
|
sys_exc_info(PyObject *self, PyObject *args)
|
||||||
|
@ -378,6 +394,7 @@ static PyMethodDef sys_methods[] = {
|
||||||
/* Might as well keep this in alphabetic order */
|
/* Might as well keep this in alphabetic order */
|
||||||
{"displayhook", sys_displayhook, 1, displayhook_doc},
|
{"displayhook", sys_displayhook, 1, displayhook_doc},
|
||||||
{"exc_info", sys_exc_info, 1, exc_info_doc},
|
{"exc_info", sys_exc_info, 1, exc_info_doc},
|
||||||
|
{"excepthook", sys_excepthook, 1, excepthook_doc},
|
||||||
{"exit", sys_exit, 0, exit_doc},
|
{"exit", sys_exit, 0, exit_doc},
|
||||||
{"getdefaultencoding", sys_getdefaultencoding, 1,
|
{"getdefaultencoding", sys_getdefaultencoding, 1,
|
||||||
getdefaultencoding_doc},
|
getdefaultencoding_doc},
|
||||||
|
@ -477,13 +494,20 @@ Dynamic objects:\n\
|
||||||
argv -- command line arguments; argv[0] is the script pathname if known\n\
|
argv -- command line arguments; argv[0] is the script pathname if known\n\
|
||||||
path -- module search path; path[0] is the script directory, else ''\n\
|
path -- module search path; path[0] is the script directory, else ''\n\
|
||||||
modules -- dictionary of loaded modules\n\
|
modules -- dictionary of loaded modules\n\
|
||||||
exitfunc -- you may set this to a function to be called when Python exits\n\
|
\n\
|
||||||
|
displayhook -- called to show results in an interactive session\n\
|
||||||
|
excepthook -- called to handle any uncaught exception other than SystemExit\n\
|
||||||
|
To customize printing in an interactive session or to install a custom\n\
|
||||||
|
top-level exception handler, assign other functions to replace these.\n\
|
||||||
|
\n\
|
||||||
|
exitfunc -- if sys.exitfunc exists, this routine is called when Python exits\n\
|
||||||
|
Assigning to sys.exitfunc is deprecated; use the atexit module instead.\n\
|
||||||
\n\
|
\n\
|
||||||
stdin -- standard input file object; used by raw_input() and input()\n\
|
stdin -- standard input file object; used by raw_input() and input()\n\
|
||||||
stdout -- standard output file object; used by the print statement\n\
|
stdout -- standard output file object; used by the print statement\n\
|
||||||
stderr -- standard error object; used for error messages\n\
|
stderr -- standard error object; used for error messages\n\
|
||||||
By assigning another file object (or an object that behaves like a file)\n\
|
By assigning other file objects (or objects that behave like files)\n\
|
||||||
to one of these, it is possible to redirect all of the interpreter's I/O.\n\
|
to these, it is possible to redirect all of the interpreter's I/O.\n\
|
||||||
\n\
|
\n\
|
||||||
last_type -- type of last uncaught exception\n\
|
last_type -- type of last uncaught exception\n\
|
||||||
last_value -- value of last uncaught exception\n\
|
last_value -- value of last uncaught exception\n\
|
||||||
|
@ -498,7 +522,7 @@ exc_traceback -- traceback of exception currently being handled\n\
|
||||||
because it is thread-safe.\n\
|
because it is thread-safe.\n\
|
||||||
"
|
"
|
||||||
#ifndef MS_WIN16
|
#ifndef MS_WIN16
|
||||||
/* Concatenating string here */
|
/* concatenating string here */
|
||||||
"\n\
|
"\n\
|
||||||
Static objects:\n\
|
Static objects:\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -512,15 +536,23 @@ platform -- platform identifier\n\
|
||||||
executable -- pathname of this Python interpreter\n\
|
executable -- pathname of this Python interpreter\n\
|
||||||
prefix -- prefix used to find the Python library\n\
|
prefix -- prefix used to find the Python library\n\
|
||||||
exec_prefix -- prefix used to find the machine-specific Python library\n\
|
exec_prefix -- prefix used to find the machine-specific Python library\n\
|
||||||
dllhandle -- [Windows only] integer handle of the Python DLL\n\
|
"
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
/* concatenating string here */
|
||||||
|
"dllhandle -- [Windows only] integer handle of the Python DLL\n\
|
||||||
winver -- [Windows only] version number of the Python DLL\n\
|
winver -- [Windows only] version number of the Python DLL\n\
|
||||||
__stdin__ -- the original stdin; don't use!\n\
|
"
|
||||||
__stdout__ -- the original stdout; don't use!\n\
|
#endif /* MS_WINDOWS */
|
||||||
__stderr__ -- the original stderr; don't use!\n\
|
"__stdin__ -- the original stdin; don't touch!\n\
|
||||||
|
__stdout__ -- the original stdout; don't touch!\n\
|
||||||
|
__stderr__ -- the original stderr; don't touch!\n\
|
||||||
|
__displayhook__ -- the original displayhook; don't touch!\n\
|
||||||
|
__excepthook__ -- the original excepthook; don't touch!\n\
|
||||||
\n\
|
\n\
|
||||||
Functions:\n\
|
Functions:\n\
|
||||||
\n\
|
\n\
|
||||||
displayhook() -- print an object to the screen, and save it in __builtin__._\n\
|
displayhook() -- print an object to the screen, and save it in __builtin__._\n\
|
||||||
|
excepthook() -- print an exception and its traceback to sys.stderr\n\
|
||||||
exc_info() -- return thread-safe information about the current exception\n\
|
exc_info() -- return thread-safe information about the current exception\n\
|
||||||
exit() -- exit the interpreter by raising SystemExit\n\
|
exit() -- exit the interpreter by raising SystemExit\n\
|
||||||
getrefcount() -- return the reference count for an object (plus one :-)\n\
|
getrefcount() -- return the reference count for an object (plus one :-)\n\
|
||||||
|
@ -530,7 +562,7 @@ setprofile() -- set the global profiling function\n\
|
||||||
setrecursionlimit() -- set the max recursion depth for the interpreter\n\
|
setrecursionlimit() -- set the max recursion depth for the interpreter\n\
|
||||||
settrace() -- set the global debug tracing function\n\
|
settrace() -- set the global debug tracing function\n\
|
||||||
"
|
"
|
||||||
#endif
|
#endif /* MS_WIN16 */
|
||||||
/* end of sys_doc */ ;
|
/* end of sys_doc */ ;
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -555,6 +587,10 @@ _PySys_Init(void)
|
||||||
PyDict_SetItemString(sysdict, "__stdin__", sysin);
|
PyDict_SetItemString(sysdict, "__stdin__", sysin);
|
||||||
PyDict_SetItemString(sysdict, "__stdout__", sysout);
|
PyDict_SetItemString(sysdict, "__stdout__", sysout);
|
||||||
PyDict_SetItemString(sysdict, "__stderr__", syserr);
|
PyDict_SetItemString(sysdict, "__stderr__", syserr);
|
||||||
|
PyDict_SetItemString(sysdict, "__displayhook__",
|
||||||
|
PyDict_GetItemString(sysdict, "displayhook"));
|
||||||
|
PyDict_SetItemString(sysdict, "__excepthook__",
|
||||||
|
PyDict_GetItemString(sysdict, "excepthook"));
|
||||||
Py_XDECREF(sysin);
|
Py_XDECREF(sysin);
|
||||||
Py_XDECREF(sysout);
|
Py_XDECREF(sysout);
|
||||||
Py_XDECREF(syserr);
|
Py_XDECREF(syserr);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue