2012-11-05 39 views
3

我正在使用同一應用程序內的gevent和龍捲風,以便不支持龍捲風的ioloop的庫可以被制服以使用gevent異步執行。我想我需要運行兩個真正的系統線程,一個專用於Tornado的ioloop,另一個專用於gevent的循環。但是,嘗試調用系統線程內的任何gevent函數將返回not implemented Error,gevent cannot be used inside threads。因此,我試圖修補猴子穿爲好,如下面的代碼片段顯示如何在單個應用程序中使用gevent和龍捲風?

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會阻止並不處理新的請求,直到舊的請求回。有人能解釋gevent如何與Tornado的ioloop互動嗎?

回答

1

我建議你看看motor lib它是pymongo驅動程序周圍的異步包裝。它使用greenlets爲龍捲風回調風格採用同步pymongo代碼。所以我認爲它應該是找到一些想法的好地方。