Python subprocesss output redirected to TD textport?

Currently using

	output = subprocess.run(shlex.split(command), capture_output=True, text=True)	
	print(output.stderr)
	print(output.stdout)

It blocks while the command is executing and will print the output and errors after it finishes

Is there a way (beside threads) to run the subprocess without blocking and getting realtime feedback/output on the TD textport?

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.

Im an absolute Asyncio beginner, but in my (limited) testing starting the asyncio event loop with run_until_complete() will block the TD event loop

https://asyncio.readthedocs.io/en/latest/subprocess.html

Or are you suggesting a different workflow?

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.

I have a thread based model working fine, but I’ve run into a new issue when running two blocking subprocesses in sequence.

Running below code will first execute both sub-processes and then print the results of both.

Is there a way to get the print of the first command show up in the textport before the second blocking process is started?

import subprocess
import time

command ="echo foo"
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
print(stdout)

#time.sleep(2)

command ="echo bar"
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
print(stdout)