Asynchronous 如何在单个应用程序中使用gevent和tornado?

Asynchronous 如何在单个应用程序中使用gevent和tornado?,asynchronous,tornado,gevent,greenlets,Asynchronous,Tornado,Gevent,Greenlets,我正致力于在同一个应用程序中使用gevent和tornado,这样不支持tornado的ioloop的库就可以使用gevent进行异步操作。我想我需要运行两个真正的系统线程,一个专用于Tornado的ioloop,另一个专用于gevent的循环。但是,尝试在系统线程内调用任何gevent函数会返回未实现错误,gevent不能在线程内使用。因此,我也尝试了monkey补丁线程,如下面的代码片段所示 from gevent import monkey; monkey.patch_all() from

我正致力于在同一个应用程序中使用gevent和tornado,这样不支持tornado的ioloop的库就可以使用gevent进行异步操作。我想我需要运行两个真正的系统线程,一个专用于Tornado的ioloop,另一个专用于gevent的循环。但是,尝试在系统线程内调用任何gevent函数会返回
未实现错误
gevent不能在线程内使用
。因此,我也尝试了monkey补丁线程,如下面的代码片段所示

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停止获取新响应时,tornado的ioloop将阻塞并在旧请求返回之前不处理新请求。有人能解释一下gevent是如何与Tornado的iLoop交互的吗?

我建议您看看lib,它是pymongo驱动程序的异步包装器。它使用greenlets采用同步pymongo代码实现tornado回调风格。所以我认为这应该是一个找到一些想法的好地方

基本思想是使用gevent对系统线程进行修补,然后在python“线程”下运行tornado,这些线程实际上是gevent Greenlet