When I use the C API to get the str() of an execption I see this text: <class 'TypeError'>
But python reports the following for the same exception: TypeError: unsupported operand type(s) for +: 'int' and 'str' What do I need to do in the C API to get the the same text for the exception? All the code I'm using is below. I have been debugging this on Fedora 29 with python 3.7.2. To repoduce the problem put the three files in a folder and run: $ py3 setup.py build $ PYTHONPATH=build/lib.linux-x86_64-3.7 python3 simple_test.py Which will output: Error: <class 'TypeError'> Traceback (most recent call last): File "simple_test.py", line 7, in <module> simple.test_error() File "simple_test.py", line 5, in simple_eval return eval( arg ) File "<string>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str' ---- setup.py --- import os os.environ['CFLAGS'] = "-O0 -g" from distutils.core import setup, Extension setup(name = 'simple', version = '1.0', ext_modules = [Extension('simple', ['simple.c'])]) --- simple.c --- #include <Python.h> #include <stdio.h> // Yes I know the ref counts are not decremented static PyObject *test_error(PyObject *self, PyObject *args) { PyObject *m = PyImport_AddModule( "__main__" ); PyObject *m_dict = PyModule_GetDict( m ); PyObject *func_args = PyTuple_New( 1 ); PyObject *str = PyUnicode_FromString( "1 + 'q'" ); PyTuple_SetItem( func_args, 0, str); PyObject *func = PyMapping_GetItemString( m_dict, "simple_eval" ); assert( func != 0 ); PyObject *result = PyObject_CallObject( func, func_args ); PyObject *err = PyErr_Occurred(); if( err != 0 ) { PyObject *u_why = PyObject_Str( err ); PyObject *b_why = PyUnicode_AsEncodedString( u_why, "utf-8", "strict" ); int size = PyBytes_Size( b_why ); char *why = PyBytes_AsString( b_why ); printf("Error: %*s\n", size, why ); return 0; } return result; } static PyMethodDef myMethods[] = { { "test_error", test_error, METH_NOARGS, "test eval with error" }, { NULL, NULL, 0, NULL } }; static struct PyModuleDef simple = { PyModuleDef_HEAD_INIT, "simple", "Simple Module", -1, myMethods }; // Initializes our module using our above struct PyMODINIT_FUNC PyInit_simple(void) { return PyModule_Create(&simple); } --- simple_test.py --- import sys import simple def simple_eval( arg ): return eval( arg ) simple.test_error() --- end -- Barry -- https://mail.python.org/mailman/listinfo/python-list