3

私は、トルネードの ioloop をサポートしていないライブラリが gevent を使用して非同期に動作するように抑制できるように、同じアプリケーション内で gevent とトルネードを使用することに取り組んでいます。2 つの実際のシステム スレッドを実行する必要があると思いました。1 つは Tornado の ioloop 専用で、もう 1 つは gevent のループ専用です。ただし、システム スレッド内で gevent 関数を呼び出そうとするとnot implemented Errorgevent cannot be used inside threads. したがって、次のスニペットが示すように、モンキー パッチ スレッドも試しました。

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 によってパッチされ、グリーン スレッドに変わった場合、一度に 1 つのスレッドしか実行されないことを意味します。つまり、gevent が新しい応答のフェッチを停止している間、tornado の ioloop はブロックされ、古い要求が完了するまで新しい要求を処理しません。戻ってきた。gevent が Tornado の ioloop とどのように相互作用するかを誰か説明できますか?

4

2 に答える 2

1

motor libを見ることをお勧めします。これは、pymongo ドライバーの非同期ラッパーです。greenlets を使用して、トルネード コールバック スタイルの同期 pymongo コードを採用しています。ですから、アイデアを見つけるには良い場所だと思います。

于 2012-11-09T22:48:14.853 に答える
0

基本的な考え方は、gevent を使用してシステム スレッドにモンキー パッチを適用し、実際には gevent greenlets である python 'threads' の下で tornado を実行することです。

gevent と tornado の併用方法

于 2015-08-20T17:40:47.067 に答える