2016-10-16 2 views
0

내가 토네이도와 파이썬에 초보자입니다 요청합니다. 며칠 전 나는 비 차단 나머지 API를 작성하기 시작했지만, 아직 임무를 완수 할 수 없었습니다. 이 끝점 "localhost : 8080/async"에 두 개의 요청을 동시에 보내면 두 번째 요청은 20 초 후에 응답합니다! 그건 내가 뭔가 잘못하고 있다고 설명한다.파이썬 토네이도 gen.coroutine 블록

MAX_WORKERS = 4 
class ASYNCHandler(tornado.web.RequestHandler): 
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS) 
    counter = 0 

    def pow_task(self, x, y): 
     time.sleep(10) 
     return pow(x,y) 

    async def background_task(self): 
     future = ASYNCHandler.executor.submit(self.pow_task, 2, 3) 
     return future 

    @gen.coroutine 
    def get(self, *args, **kwargs): 
     future = yield from self.background_task() 
     response= dumps({"result":future.result()}, default=json_util.default) 
     print(response) 


application = tornado.web.Application([ 
     ('/async', ASYNCHandler), 
     ('/sync', SYNCHandler), 
    ], db=db, debug=True) 
application.listen(8888) 
tornado.ioloop.IOLoop.current().start() 

답변

0

ThreadPoolExecutor 미래, 기본적으로 블록 토네이도의 이벤트 루프를 반환. 토네이도 팀의 누군가가 이것을 읽고 이유가 무엇인지 알고 있다면 설명을 해줄 수 있습니까? 나는 토네이도 스레드 몇 가지 물건을 할 계획했지만이 문제를 처리 한 후, 나는 내가 원래 예상처럼 간단 할 수 없을거야 것을 알 수있다. 어떤 경우에는, 여기에 당신이 무엇을 기대 수행하는 코드이다 (사람이 신속하게 실행할 수 있도록 내가 조금 원래 예를 손질 한) :

from concurrent.futures import ThreadPoolExecutor 
from json import dumps 
import time 
from tornado.platform.asyncio import to_tornado_future 
from tornado.ioloop import IOLoop 
from tornado import gen, web 

MAX_WORKERS = 4 

class ASYNCHandler(web.RequestHandler): 
    executor = ThreadPoolExecutor(max_workers=MAX_WORKERS) 
    counter = 0 

    def pow_task(self, x, y): 
     time.sleep(5) 
     return pow(x,y) 

    async def background_task(self): 
     future = self.executor.submit(self.pow_task, 2, 3) 
     result = await to_tornado_future(future) # convert to tornado future 
     return result 

    @gen.coroutine 
    def get(self, *args, **kwargs): 
     result = yield from self.background_task() 
     response = dumps({"result": result}) 
     self.write(response) 


application = web.Application([ 
     ('/async', ASYNCHandler), 
    ], debug=True) 
application.listen(8888) 
IOLoop.current().start() 

주요 차이는 background_tasks() 방법에 있습니다. 나는 그 결과를 반환, 결과를 기다릴하는 tornado 미래에 asyncio 미래를 변환합니다. 이 질문에 제공되는 코드는 background_task()에서 항복 할 때 어떤 이유로 차단 및 미래 토네이도 미래를하지 않았기 때문에 당신은 await에 결과 수 없었습니다. 약간 다른 노트에

,이 간단한 예는 쉽게 단일 스레드/비동기 디자인을 사용하여 구현 될 수 있으며, 기회는 당신의 코드는 스레드없이 할 수 있습니다. 쓰래드는 쉽게 구현할 수 있지만 잘못되게 쉽고 매우 끈적한 상황을 초래할 수 있습니다. 스레드 코드를 작성하려고 할 때 this photo을 기억하시기 바랍니다 :

관련 문제