@@ -1334,7 +1334,7 @@ TPythonInterface=class(TDynamicDll)
1334
1334
PyErr_BadInternalCall: procedure; cdecl;
1335
1335
PyErr_CheckSignals: function: integer; cdecl;
1336
1336
PyErr_Clear: procedure; cdecl;
1337
- PyErr_Fetch: procedure( errtype, errvalue, errtraceback: PPPyObject ); cdecl;
1337
+ PyErr_Fetch: procedure(out errtype, errvalue, errtraceback: PPyObject ); cdecl;
1338
1338
PyErr_NoMemory: function: PPyObject; cdecl;
1339
1339
PyErr_Occurred: function: PPyObject; cdecl;
1340
1340
PyErr_Print: procedure; cdecl;
@@ -1732,7 +1732,7 @@ TPythonTraceback = class
1732
1732
destructor Destroy; override;
1733
1733
1734
1734
procedure Clear ;
1735
- procedure Refresh ;
1735
+ procedure Refresh (pytraceback: PPyObject = nil ) ;
1736
1736
procedure AddItem (const Context, FileName: string; LineNo: Integer);
1737
1737
1738
1738
property ItemCount : Integer read GetItemCount;
@@ -2740,6 +2740,8 @@ implementation
2740
2740
(* ******************************************************)
2741
2741
resourcestring
2742
2742
SPyConvertionError = ' Conversion Error: %s expects a %s Python object' ;
2743
+ SPyExcStopIteration = ' Stop Iteration' ;
2744
+ SPyExcSystemError = ' Unhandled SystemExit exception. Code: %s' ;
2743
2745
2744
2746
(* ******************************************************)
2745
2747
(* * **)
@@ -3853,7 +3855,7 @@ procedure TPythonTraceback.Clear;
3853
3855
* simply use the method CheckError wich will call PyErr_Print,
3854
3856
* Traceback.Refresh and RaiseError for you.
3855
3857
}
3856
- procedure TPythonTraceback.Refresh ;
3858
+ procedure TPythonTraceback.Refresh (pytraceback: PPyObject) ;
3857
3859
var
3858
3860
tb, tb1 : PPyObject;
3859
3861
obj : PPyObject;
@@ -3872,7 +3874,9 @@ procedure TPythonTraceback.Refresh;
3872
3874
limitv := PySys_GetObject(' tracebacklimit' );
3873
3875
if Assigned(limitv) and PyLong_Check(limitv) then
3874
3876
alimit := PyLong_AsLong(limitv);
3875
- tb := PySys_GetObject(' last_traceback' );
3877
+ tb := pytraceback;
3878
+ if tb = nil then
3879
+ tb := PySys_GetObject(' last_traceback' );
3876
3880
tb1 := tb;
3877
3881
Py_XIncRef(tb1);
3878
3882
depth := 0 ;
@@ -4466,10 +4470,9 @@ function TPythonEngine.EvalPyFunction(pyfunc, pyargs:PPyObject): Variant;
4466
4470
presult := PyEval_CallObjectWithKeywords(pyfunc,pyargs, nil );
4467
4471
CheckError(False);
4468
4472
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
4473
4476
else
4474
4477
begin
4475
4478
try
@@ -5774,14 +5777,32 @@ procedure TPythonEngine.ListToSet( List : PPyObject; data : Pointer; size : Inte
5774
5777
end ;
5775
5778
5776
5779
procedure 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;
5777
5794
begin
5778
- if PyErr_Occurred <> nil then
5795
+ PyException := PyErr_Occurred;
5796
+ if PyException <> nil then
5779
5797
begin
5780
- if ACatchStopEx and (PyErr_GivenExceptionMatches(PyErr_Occurred , PyExc_StopIteration^) <> 0 ) then
5798
+ if ACatchStopEx and (PyErr_GivenExceptionMatches(PyException , PyExc_StopIteration^) <> 0 ) then
5781
5799
begin
5782
5800
PyErr_Clear;
5783
- raise EPyStopIteration.Create( ' Stop iteration ' );
5801
+ raise EPyStopIteration.CreateRes(@SPyExcStopIteration );
5784
5802
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
5785
5806
else
5786
5807
begin
5787
5808
PyErr_Print;
0 commit comments