Error handling when embedding python...
Dave Cole
djc at object-craft.com.au
Fri Jan 24 08:51:23 EST 2003
>>>>> "Martin" == Martin v Löwis <martin at v.loewis.de> writes:
Martin> Axel Schlueter wrote:
>> while trying to embed python as a scripting possibility into my
>> application, I stumbled across error handling. If python finds a
>> syntax error, the interpreter prints its error messages to stderr,
>> but I would like to open my own error dialog box containing the
>> message. Is there anything like an error callback hook or something
>> ?
Martin> How do you invoke the Python code? Python will not, normally,
Martin> print an error on stderr, but will return a NULL value from
Martin> the API, with a SyntaxError set.
This is a test program I wrote when I embedded Python (on Windows).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <stdarg.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <Python.h>
static PyObject *traceback_module;
static PyObject *string_module;
static PyObject *winmain_func;
static PyObject *import_module(char *name)
{
PyObject *str, *module;
char msg[128];
str = PyString_FromString(name);
if (str == NULL)
return NULL;
module = PyImport_Import(str);
Py_DECREF(str);
if (module == NULL) {
sprintf(msg, "Could not import %s module", name);
MessageBox(NULL, msg, "Python Error", MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL);
return NULL;
}
return module;
}
static void python_error()
{
PyObject *exc = NULL, *value = NULL, *trace = NULL,
*func = NULL,
*lines = NULL,
*str = NULL,
*obj = NULL;
// exc, value, trace = sys.exc_info()
PyErr_Fetch(&exc, &value, &trace);
// import traceback
if (traceback_module == NULL)
traceback_module = import_module("traceback");
if (traceback_module == NULL)
goto error;
// lines = traceback.format_exception(exc, value, trace, 20)
obj = PyModule_GetDict(traceback_module);
func = PyDict_GetItemString(obj, "format_exception");
Py_DECREF(obj); obj = NULL;
if (func == NULL)
goto error;
lines = PyObject_CallFunction(func, "OOOi", exc, value, trace, 20);
if (lines == NULL)
goto error;
Py_DECREF(func); func = NULL;
// import string
if (string_module == NULL)
string_module = import_module("string");
if (string_module == NULL)
goto error;
// str = string.join(lines)
obj = PyModule_GetDict(string_module);
func = PyDict_GetItemString(obj, "join");
Py_DECREF(obj); obj = NULL;
if (func == NULL)
goto error;
str = PyObject_CallFunction(func, "O", lines);
if (str == NULL)
goto error;
Py_DECREF(func); func = NULL;
MessageBox(NULL, PyString_AsString(str), "Python Error", MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL);
error:
Py_XDECREF(exc); Py_XDECREF(value); Py_XDECREF(trace);
Py_XDECREF(func);
Py_XDECREF(lines);
Py_XDECREF(str);
Py_XDECREF(obj);
PyErr_Clear();
}
static void python_init_module(char *name)
{
PyObject *obj = NULL, *mod = NULL, *dict = NULL;
Py_Initialize();
obj = PyString_FromString(name);
if (obj != NULL) {
mod = PyImport_Import(obj);
if (PyErr_Occurred())
mod = NULL;
}
if (mod != NULL)
dict = PyModule_GetDict(mod);
if (dict != NULL)
winmain_func = PyDict_GetItemString(dict, "winmain");
Py_XDECREF(obj);
Py_XDECREF(mod);
Py_XDECREF(dict);
}
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_line, int cmd_show)
{
PyObject *obj;
int ret;
python_init_module(cmd_line);
if (winmain_func == NULL) {
python_error();
return 0;
}
ret = 0;
obj = PyObject_CallFunction(winmain_func, "iisi", inst, prev_inst, cmd_line, cmd_show);
if (obj != NULL)
ret = PyInt_AsLong(obj);
Py_XDECREF(obj);
if (PyErr_Occurred())
python_error();
return ret;
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Because I am also an idiot I fiddled around with making a swig-free
thin wrapper around some of the Platform SDK (don't ask).
Here is the Hello Windows program...
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
from sdk32 import *
ps = PAINTSTRUCT()
rect = RECT()
def wnd_proc(wnd, msg, wparam, lparam):
global ps, rect
if msg == WM_PAINT:
dc = BeginPaint(wnd, ps)
GetClientRect(wnd, rect)
DrawText(dc, 'Hello Windows!', -1, rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER)
EndPaint(wnd, ps)
return 0
elif msg == WM_DESTROY:
PostQuitMessage(0)
return 0
return DefWindowProc(wnd, msg, wparam, lparam)
def winmain(inst, prev_inst, cmd_line, cmd_show):
app_name = 'HelloWin'
wc = WNDCLASSEX()
wc.style = CS_HREDRAW | CS_VREDRAW
wc.wnd_proc = wnd_proc
wc.inst = inst
wc.cursor = LoadCursor(0, IDC_ARROW)
wc.background = GetStockObject(WHITE_BRUSH)
wc.name = app_name
RegisterClassEx(wc)
wnd = CreateWindow(app_name, 'The Hello Program', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, inst, 0)
ShowWindow(wnd, cmd_show)
UpdateWindow(wnd)
msg = MSG()
while 1:
if not GetMessage(msg, 0, 0, 0):
break
TranslateMessage(msg)
DispatchMessage(msg)
return msg.wparam
if __name__ == '__main__':
winmain(GetModuleHandle(None), 0, '', SW_SHOWNORMAL)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
http://www.object-craft.com.au
More information about the Python-list
mailing list