When a subprocess writes to a pipe (or a file) as opposed to the terminal, it is usually the case that the output is buffered; the output is only written once it has accumulated to a certain point (often 4kB) or when the output channel is closed or the program exits (both of which will trigger a flush of everything that remains). If the program's behaviour is to slowly trickle a few bytes out, it will seem as if the program has hung. It hasn't; it's just that you're waiting for the program to do its magic.
Why doesn't tracert
have this behaviour? Simple: it's either explicitly flushing its internal buffers after every line, or not buffering at all and just writing the bytes directly as it has them. When a program is producing a lot of output that's slower (because it ends up doing a lot more system calls) but when there's not much output it's not a Big Deal in the first place. In short, tracert
isn't a good model for the program you've got a problem with.
I notice from your screen capture that the real problem may well be with a Python program that is buffering its output. There are a number of techniques on dealing with this described in this Stack Overflow question: Disable output buffering. I would try setting the environment variable first, as that's easy to do from Tcl:
set ::env(PYTHONUNBUFFERED) yes
However, in general there are other ways to tackle this from the Tcl side. The main one to mention is to use the Tcl extension, Expect. That does some evil OS hackery behind the scenes to make it appear as if the program is running in interactive mode, triggering different buffering behaviour.
package require Expect
set my_cmd "tracert google.com"
puts "Now executing the command '$my_cmd':"
spawn {*}$my_cmd
#process command output
expect {
-re {([^\r\n]+)[\r\n]} { ### Match a whole line
set line $expect_out(1,string)
### This is where your code from inside your loop goes
puts $line
### Match the next line
exp_continue
}
eof { ### Special clause for End-Of-File; which is effectively empty
}
}
close
That's a very simple use of Expect (it can also interact with the subprogram on your behalf) but it is a basic translation of your program.