2015-08-14 4 views
3

В настоящее время я работаю над своим веб-сервером Backend, используя торнадо.Как сделать async RequestHandler в tornado python

Проблема у меня прямо сейчас:
- когда сделан запрос, а сервер обработки запроса все другие запрос блокированы

Мой RequestHandler:

class UpdateServicesRequestHandler(RequestHandler): 

    @gen.coroutine 
    def get(self): 

     update = ServiceUpdate() 
     response = yield update.update_all() 

     if self.request.headers.get('Origin'): 
      self.set_header('Access-Control-Allow-Origin', self.request.headers.get('Origin')) 
     self.set_header('Content-Type', 'application/json') 
     self.write(response) 

Мои update_all():

@gen.coroutine 
def update_all(self): 

    for service in self.port_list: 
     response = yield self.update_service(str(service.get('port'))) 
     self.response_list.append(response) 

    self.response = json.dumps(self.response_list) 

    return self.response 

My update_sevice():

process = Popen([ command ], stdout=PIPE, stderr=PIPE, shell=True) 
output, error = process.communicate() 

Дело в том, что мне нужен результат метода update_all(). Итак, есть ли возможность сделать этот запрос не блокирующим весь сервер для запросов?

Спасибо!

+0

Является ли 'update.update_all()' сопроцессором? Использует ли он неблокирующий ввод-вывод для выполнения своей работы? – dano

+0

только что обновил мой пост .. – daB0bby

+0

Теперь нам нужно знать, что выглядит 'update_service'. :) В конечном счете, нам нужно знать, если вы делаете медленный блокирующий вызов где-то внутри 'update_all'. – dano

ответ

2

Вы должны использовать обертку Tornado вокруг subprocess.Popen, чтобы избежать блокировки цикл событий:

from tornado.process import Subprocess 
from subprocess import PIPE 
from tornado import gen 

@gen.coroutine 
def run_command(command): 
    process = Subprocess([command], stdout=PIPE, stderr=PIPE, shell=True) 
    yield process.wait_for_exit() # This waits without blocking the event loop. 
    out, err = process.stdout.read(), process.stderr.read() 
    # Do whatever you do with out and err 
+0

Это действительно помогло мне! Большое спасибо!! :-) – daB0bby

4

В дополнение к использованию tornado.process.Subprocess, как предполагает Дано, вы должны использовать stdout=tornado.process.Subprocess.STREAM вместо PIPE и читать стандартный вывод/STDERR асинхронно , Использование PIPE будет работать для небольших объемов вывода, но вы будете заторможены в wait_for_exit(), если используете PIPE, и подпроцесс пытается записать слишком много данных (используется для 4 КБ, но предел выше в большинстве современных Linux-систем).

process = Subprocess([command], 
    stdout=Subprocess.STREAM, stderr=Subprocess.STREAM, 
    shell=True) 
out, err = yield [process.stdout.read_until_close(), 
    process.stderr.read_until_close()] 
+0

Что такое идиоматический способ получения кода возврата и создания исключения, если в этом случае ненулевой? Спасибо - –

+1

'yield process.wait_for_exit()': http://www.tornadoweb.org/en/stable/process.html#tornado.process.Subprocess.wait_for_exit –

Смежные вопросы