2012-11-05 6 views
3

토네이도의 ioloop을 지원하지 않는 라이브러리가 gevent를 사용하여 비동기 적으로 작동하도록 억제 될 수 있도록 geent와 tornado를 동일한 응용 프로그램 내에서 사용하고 있습니다. 두 개의 실제 시스템 스레드 (토네이도의 ioloop 전용 및 다른 하나는 gevent 루프 전용)를 실행해야한다고 생각했습니다. 그러나 시스템 스레드 내에서 gevent 함수를 호출하려고하면 not implemented Error, gevent cannot be used inside threads을 반환합니다. 따라서, 나는 다음 코드가 계속gevent 및 tornado를 단일 응용 프로그램에서 사용하는 방법?

from gevent import monkey; monkey.patch_all() 
from random import choice 
import gevent 
import requests 
import tornado.ioloop 
import tornado.web 
import threading 
import Queue 

q = Queue.Queue() 

i = 0 
def synchronous_get_url(url, callback=None): 
    global i 
    i += 1 
    d = i 

    print('bar %d getting %s' % (d, url)) 
    requests.get(url) 
    print('bar %d finished getting %s' % (d, url)) 
    if callback: 
     callback() 

class GreenEventLoop(threading.Thread): 
    daemon = True 
    def run(self): 
     while True: 
      url, callback = q.get() 
      gevent.spawn(synchronous_get_url, url, callback) 

을 같이 원숭이 패치는 별도의 프로세스에서 ...뿐만 아니라

class MainHandler(tornado.web.RequestHandler): 

    @tornado.web.asynchronous 
    def get(self): 
     print 'Received get request' 
     urls = [ 
      'http://google.com', 
      'http://apple.com', 
      'http://microsoft.com', 
      'http://github.com', 
      'http://sourceforge.com', 
     ] 

     q.put((choice(urls), self._on_fetch), block=False) 
     self.write("submitted url to queue") 

    def _on_fetch(self): 
     print 'Finishing in the handler\n' 
     try: 
      self.finish() 
     except: 
      pass 

# Start GEvent Loop 
green_loop = GreenEventLoop() 
green_loop.start() 

# Start Tornado Loop 
application = tornado.web.Application([ 
    (r"/", MainHandler), 
    ], debug=True) 
application.listen(7001) 
tornado.ioloop.IOLoop.instance().start() 

스레딩 명령 행에서, 나는 다음을 실행했습니다.

from gevent import monkey; monkey.patch_all() 
import gevent 
import requests 
count = 0 
def get_stuff(i): 
    global count 
    res = requests.get('http://localhost:7000/') 
    count += 1 
    print count, res, i 

lets = [gevent.spawn(get_stuff, i) for i in range(15)] 
gevent.joinall(lets) 

이렇게하면 15 개의 URL을 동시에 검색하고 수신 된 응답을 반환 할 수 있습니다. 왜 내가 위의 코드가 전혀 작동하는지 이해하지 못합니다. 스레딩이 gevent로 패치되고 녹색 스레드로 바뀌면 한 번에 하나의 스레드 만 실행된다는 것을 의미합니다. 즉, gevent가 새 응답을 가져 오는 동안 토네이도의 ioloop은 차단하고 이전 요청이 처리 될 때까지 새로운 요청을 처리하지 않습니다. 반환되었습니다. 누군가가 georn이 Tornado의 ioloop과 상호 작용하는 방법을 설명 할 수 있습니까?

답변

1

가 나는 pymongo 드라이버 주위 비동기 래퍼 해방이 motor 보면 좋습니다. 그것은 greenlet을 사용하여 토네이도 콜백 스타일을위한 동기 pymongo 코드를 채택합니다. 그래서 나는 그것이 어떤 아이디어를 찾기에 좋은 장소라고 생각합니다.

0

기본 아이디어는 정말 gevent greenlets있는 '스레드'다음 시스템 스레드를 패치 원숭이에 gevent을 사용하여 파이썬에서 토네이도 실행하는 것입니다.

How to use gevent and tornado together