@@ -11,6 +11,9 @@ import 'gen.dart';
1111export 'gen.dart' ;
1212
1313CPython ? _cpython;
14+ // Keep a single interpreter per process; repeated init/finalize of CPython 3.12
15+ // from an embedder is fragile and was crashing on second launch.
16+ bool _pythonInitialized = false ;
1417
1518CPython getCPython (String dynamicLibPath) {
1619 return _cpython ?? = _cpython = CPython (DynamicLibrary .open (dynamicLibPath));
@@ -51,33 +54,43 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
5154 debugPrint ("programModuleName: $programModuleName " );
5255
5356 final cpython = getCPython (dynamicLibPath);
54- cpython.Py_Initialize ();
55- debugPrint ("after Py_Initialize()" );
57+ if (! _pythonInitialized) {
58+ cpython.Py_Initialize ();
59+ _pythonInitialized = true ;
60+ debugPrint ("after Py_Initialize()" );
61+ } else {
62+ debugPrint ("Python already initialized; reusing interpreter" );
63+ }
5664
5765 var result = "" ;
58-
59- if (script != "" ) {
60- // run script
61- final scriptPtr = script.toNativeUtf8 ();
62- int sr = cpython.PyRun_SimpleString (scriptPtr.cast <Char >());
63- debugPrint ("PyRun_SimpleString for script result: $sr " );
64- malloc.free (scriptPtr);
65- if (sr != 0 ) {
66- result = getPythonError (cpython);
67- }
68- } else {
69- // run program
70- final moduleNamePtr = programModuleName.toNativeUtf8 ();
71- var modulePtr = cpython.PyImport_ImportModule (moduleNamePtr.cast <Char >());
72- if (modulePtr == nullptr) {
73- result = getPythonError (cpython);
66+ // Ensure the current native thread is registered with the GIL; this is
67+ // required if we re-enter Python from a new Dart isolate/thread.
68+ final gilState = cpython.PyGILState_Ensure ();
69+
70+ try {
71+ if (script != "" ) {
72+ // run script
73+ final scriptPtr = script.toNativeUtf8 ();
74+ int sr = cpython.PyRun_SimpleString (scriptPtr.cast <Char >());
75+ debugPrint ("PyRun_SimpleString for script result: $sr " );
76+ malloc.free (scriptPtr);
77+ if (sr != 0 ) {
78+ result = getPythonError (cpython);
79+ }
80+ } else {
81+ // run program
82+ final moduleNamePtr = programModuleName.toNativeUtf8 ();
83+ var modulePtr =
84+ cpython.PyImport_ImportModule (moduleNamePtr.cast <Char >());
85+ if (modulePtr == nullptr) {
86+ result = getPythonError (cpython);
87+ }
88+ malloc.free (moduleNamePtr);
7489 }
75- malloc.free (moduleNamePtr);
90+ } finally {
91+ cpython.PyGILState_Release (gilState);
7692 }
7793
78- cpython.Py_Finalize ();
79- debugPrint ("after Py_Finalize()" );
80-
8194 sendPort.send (result);
8295
8396 return result;
0 commit comments