For instance, suppose I have this code:
def dump():
tcpdump = subprocess.Popen("tcpdump -nli any",
stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
outputfile = tcpdump.stdout
for line in outputfile:
print line,
How can I serve the output of such to the browser? Since there is no stopping point, I have no idea where to hook with the polling loop. More than that, as print line works (I see lines dumped on the terminal), browser do not get the very same lines, see below:
@tornado.web.asynchronous
def post(self):
tcpdump = subprocess.Popen("tcpdump -nli any",
stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
outputfile = tcpdump.stdout
for line in outputfile:
print line,
self.write(line)
self.finish()
Calling flush() is necessary but not sufficient - flushed output still won't actually be sent if the IOLoop is blocked reading from the subprocess's pipe. You need to either move the readline loop to a separate thread (probably the simplest approach) or make it asynchronous. Making it asynchronous would require using fcntl to set the O_NONBLOCK flag, adding a handler to the IOLoop to get notified when there is new data, and using read() instead of readline() (see http://stackoverflow.com/questions/375427/non-blocking-read-on-a-stream-in-python). It shouldn't be too hard to adapt IOStream to work with pipes in addition to sockets.