@@ -1334,7 +1334,7 @@ TPythonInterface=class(TDynamicDll)
13341334 PyErr_BadInternalCall: procedure; cdecl;
13351335 PyErr_CheckSignals: function: integer; cdecl;
13361336 PyErr_Clear: procedure; cdecl;
1337- PyErr_Fetch: procedure( errtype, errvalue, errtraceback: PPPyObject ); cdecl;
1337+ PyErr_Fetch: procedure(out errtype, errvalue, errtraceback: PPyObject ); cdecl;
13381338 PyErr_NoMemory: function: PPyObject; cdecl;
13391339 PyErr_Occurred: function: PPyObject; cdecl;
13401340 PyErr_Print: procedure; cdecl;
@@ -1732,7 +1732,7 @@ TPythonTraceback = class
17321732 destructor Destroy; override;
17331733
17341734 procedure Clear ;
1735- procedure Refresh ;
1735+ procedure Refresh (pytraceback: PPyObject = nil ) ;
17361736 procedure AddItem (const Context, FileName: string; LineNo: Integer);
17371737
17381738 property ItemCount : Integer read GetItemCount;
@@ -2740,6 +2740,8 @@ implementation
27402740(* ******************************************************)
27412741resourcestring
27422742SPyConvertionError = ' Conversion Error: %s expects a %s Python object' ;
2743+ SPyExcStopIteration = ' Stop Iteration' ;
2744+ SPyExcSystemError = ' Unhandled SystemExit exception. Code: %s' ;
27432745
27442746(* ******************************************************)
27452747(* * **)
@@ -3853,7 +3855,7 @@ procedure TPythonTraceback.Clear;
38533855 * simply use the method CheckError wich will call PyErr_Print,
38543856 * Traceback.Refresh and RaiseError for you.
38553857}
3856- procedure TPythonTraceback.Refresh ;
3858+ procedure TPythonTraceback.Refresh (pytraceback: PPyObject) ;
38573859var
38583860 tb, tb1 : PPyObject;
38593861 obj : PPyObject;
@@ -3872,7 +3874,9 @@ procedure TPythonTraceback.Refresh;
38723874 limitv := PySys_GetObject(' tracebacklimit' );
38733875 if Assigned(limitv) and PyLong_Check(limitv) then
38743876 alimit := PyLong_AsLong(limitv);
3875- tb := PySys_GetObject(' last_traceback' );
3877+ tb := pytraceback;
3878+ if tb = nil then
3879+ tb := PySys_GetObject(' last_traceback' );
38763880 tb1 := tb;
38773881 Py_XIncRef(tb1);
38783882 depth := 0 ;
@@ -4466,10 +4470,9 @@ function TPythonEngine.EvalPyFunction(pyfunc, pyargs:PPyObject): Variant;
44664470 presult := PyEval_CallObjectWithKeywords(pyfunc,pyargs, nil );
44674471 CheckError(False);
44684472 if presult = nil then
4469- begin
4470- PyErr_Print;
4471- RaiseError;
4472- end
4473+ // should not happen since an exception would have been raised
4474+ // in that case by CheckError
4475+ Result := Null
44734476 else
44744477 begin
44754478 try
@@ -5774,14 +5777,32 @@ procedure TPythonEngine.ListToSet( List : PPyObject; data : Pointer; size : Inte
57745777end ;
57755778
57765779procedure TPythonEngine.CheckError (ACatchStopEx : Boolean = False);
5780+ procedure ProcessSystemExit ;
5781+ var
5782+ errtype, errvalue, errtraceback: PPyObject;
5783+ SErrValue: string;
5784+ begin
5785+ PyErr_Fetch(errtype, errvalue, errtraceback);
5786+ Traceback.Refresh(errtraceback);
5787+ SErrValue := PyObjectAsString(errvalue);
5788+ PyErr_Clear;
5789+ raise EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]);
5790+ end ;
5791+
5792+ var
5793+ PyException: PPyObject;
57775794begin
5778- if PyErr_Occurred <> nil then
5795+ PyException := PyErr_Occurred;
5796+ if PyException <> nil then
57795797 begin
5780- if ACatchStopEx and (PyErr_GivenExceptionMatches(PyErr_Occurred , PyExc_StopIteration^) <> 0 ) then
5798+ if ACatchStopEx and (PyErr_GivenExceptionMatches(PyException , PyExc_StopIteration^) <> 0 ) then
57815799 begin
57825800 PyErr_Clear;
5783- raise EPyStopIteration.Create( ' Stop iteration ' );
5801+ raise EPyStopIteration.CreateRes(@SPyExcStopIteration );
57845802 end
5803+ else if PyErr_GivenExceptionMatches(PyException, PyExc_SystemExit^) <> 0 then
5804+ // Special treatment for SystemExit. Calling PyErr_Print would terminate the process
5805+ ProcessSystemExit
57855806 else
57865807 begin
57875808 PyErr_Print;
0 commit comments