Skip to content

Commit 3f6b044

Browse files
committed
Refactor Python FFI execution and isolate handling
Simplifies sync and async execution paths for running Python programs via FFI. Moves core execution logic to a private function, improves error handling, and ensures proper resource cleanup in async mode. Removes redundant message passing and streamlines isolate communication.
1 parent 91eb676 commit 3f6b044

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

src/serious_python_android/lib/src/cpython.dart

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,20 @@ CPython getCPython(String dynamicLibPath) {
4545

4646
Future<String> runPythonProgramFFI(bool sync, String dynamicLibPath,
4747
String pythonProgramPath, String script) async {
48-
final receivePort = ReceivePort();
4948
if (sync) {
50-
// sync run
51-
return await runPythonProgramInIsolate(
52-
[receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
49+
// Sync run: do not involve ports (avoids GC/close races).
50+
return _runPythonProgram(dynamicLibPath, pythonProgramPath, script);
5351
} else {
54-
var completer = Completer<String>();
55-
// async run
56-
final isolate = await Isolate.spawn(runPythonProgramInIsolate,
57-
[receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
58-
receivePort.listen((message) {
52+
// Async run: execute in a separate isolate and await exactly one result.
53+
final receivePort = ReceivePort();
54+
try {
55+
await Isolate.spawn(runPythonProgramInIsolate,
56+
[receivePort.sendPort, dynamicLibPath, pythonProgramPath, script]);
57+
final message = await receivePort.first;
58+
return message is String ? message : message.toString();
59+
} finally {
5960
receivePort.close();
60-
isolate.kill();
61-
completer.complete(message);
62-
});
63-
return completer.future;
61+
}
6462
}
6563
}
6664

@@ -70,6 +68,20 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
7068
final pythonProgramPath = arguments[2] as String;
7169
final script = arguments[3] as String;
7270

71+
try {
72+
final result = _runPythonProgram(dynamicLibPath, pythonProgramPath, script);
73+
sendPort.send(result);
74+
return result;
75+
} catch (e, st) {
76+
final message = "Dart error running Python: $e\n$st";
77+
spDebug(message);
78+
sendPort.send(message);
79+
return message;
80+
}
81+
}
82+
83+
String _runPythonProgram(
84+
String dynamicLibPath, String pythonProgramPath, String script) {
7385
var programDirPath = p.dirname(pythonProgramPath);
7486
var programModuleName = p.basenameWithoutExtension(pythonProgramPath);
7587

@@ -81,7 +93,6 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
8193
spDebug("CPython loaded");
8294
if (cpython.Py_IsInitialized() != 0) {
8395
spDebug("Python already initialized, skipping execution.");
84-
sendPort.send("");
8596
return "";
8697
}
8798

@@ -93,7 +104,6 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
93104
final logcatSetupError = _setupLogcatForwarding(cpython);
94105
if (logcatSetupError != null) {
95106
cpython.Py_Finalize();
96-
sendPort.send(logcatSetupError);
97107
return logcatSetupError;
98108
}
99109

@@ -119,8 +129,6 @@ Future<String> runPythonProgramInIsolate(List<Object> arguments) async {
119129
cpython.Py_Finalize();
120130
spDebug("after Py_Finalize()");
121131

122-
sendPort.send(result);
123-
124132
return result;
125133
}
126134

0 commit comments

Comments
 (0)