I don't know the answer but I know a thing or two that might be useful. By starting the command with "&", as you have, you avoid the proc.communicate() call, which would block Leo until it returns. However, if you try to capture output with a pipe, the pipe can block if it fills up, and that happens with a surprisingly small number of bytes. Then you block because the pipe is waiting to be cleared, and you are probably waiting to get output from the pipe.
So that won't work.
The way I managed this with the background process manager (BPM) - it's what launches pylint, mypy, etc - is to use a separate thread to launch the process, and call proc.communicate() in that thread. The thread blocks waiting for the process to complete, but that doesn't matter since it doesn't block Leo itself. This leaves the question of how to get the results. The thread puts the results into a variable in the BPM, and the BPM registers a callback at idle time. The callback checks to see if the variable is not None. If the BPM sees that there is a result in that variable, it cancels the callback and makes use of the result. Then it writes the messages to the log pane. You have to use a lock to make sure that the external process's results are put atomically into the variable. In your case I might have it write the results to a different tab to avoid getting mixed up with regular log output. I'm going by memory here and might have a detail or two inaccurate.
So study the BPM and see if you could do something similar with your code. The BPM makes sure that it only ever runs one process at a time, BTW. That avoids the possibility of getting intermingled results or other confusions.
Another possibility is to have your external process redirect output to a known file. You could check periodically to see if that file has gotten new data and read the new data if so. The problem there might be to know when the external process is finished writing data. You could also hget a race condition between the writing process and the reading process, so you would have to figure out how to handle that situation. I don't happen to know how that works and it might be different between Windows and Linux.
Another possibility would be to launch your external program from a batch/shell file and have the batch/shell file redirect the output to a known file. When the programs finishes, the batch file could set an environmental variable. You could do the idle-time callback trick to check for that variable, or you could have the checks done periodically by a separate thread. That thread could even read the results, format them, and write them to a new tab or pass them on to another batch file.
I would say the last possibility sounds the most promising to me.