Home

Tags

Async subprocess for tornado

2012-07-30 python tornado web async subprocess

Пример асинхронного запуска процесса через subprocess из tornado.

Построчная выборка

import tornado.httpserver
import tornado.ioloop
import tornado.web
import subprocess

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        cmd = 'sleep 3; echo "1\n2\n3\n"; sleep 3; date; sleep 3'

        def send(data):
            if data:
                self.write(data)
                self.flush()
            else:
                self.finish()

        self.subprocess(cmd, send)

    def subprocess(self, cmd, callback):
        ioloop = tornado.ioloop.IOLoop.instance()
        PIPE = subprocess.PIPE
        pipe = subprocess.Popen(cmd , shell=True, stdin=PIPE, stdout=PIPE,
                            stderr=subprocess.STDOUT, close_fds=True)
        fd = pipe.stdout.fileno()

        def recv(*args):
            data = pipe.stdout.readline()
            if data: callback(data)
            elif pipe.poll() is not None:
                ioloop.remove_handler(fd)
                callback(None)

        # read handler
        ioloop.add_handler(fd, recv, ioloop.READ)

class TestHandler(tornado.web.RequestHandler):
    def get(self):
        self.write('Test')

application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/test/", TestHandler),
], debug=True)

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()


Если нужен только конечный результат
import tornado.httpserver
import tornado.ioloop
import tornado.web
import subprocess
from tornado import gen

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    @gen.engine
    def get(self):
        cmd = 'sleep 3; echo "1\n2\n3\n"; sleep 3; date; sleep 3'
        result = yield gen.Task(self.subprocess, cmd)
        self.finish(result)

    def subprocess(self, cmd, callback):
        ioloop = tornado.ioloop.IOLoop.instance()
        PIPE = subprocess.PIPE
        pipe = subprocess.Popen(cmd , shell=True, stdin=PIPE, stdout=PIPE,
                        stderr=subprocess.STDOUT, close_fds=True)
        fd = pipe.stdout.fileno()
        result = []

        def recv(*args):
            data = pipe.stdout.readline()
            if data: result.append(data)
            elif pipe.poll() is not None:
                ioloop.remove_handler(fd)
                callback(''.join(result))

        ioloop.add_handler(fd, recv, ioloop.READ)

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start()