I don’t think you can do this particular action without threads since you’re essentially invoking a subprocess that you want data back from. You could send data back from the subprocess as a UDP packet - then log / print that info. I don’t know that’s helpful in your circumstance or not.
One other option might be to use the asyncio system to spawn a subprocess that writes events to a shared queue. You could then poll that queue in the TD event loop and print to the textport as needed.
Theoretically if you call an async function in your subprocess you can await its conclusion and cede control back to the main thread. I have not tested this specifically with TD’s event loop and it may not handle the scenario as expected, but if there’s interest from the community perhaps Derivative would consider it.
This is a pretty good resource for getting started with asyncio. I’ve found most of the other documentation to be fairly confusing as there are many conflicting examples out there.