2016-05-31 7 views
0

私はコルーチンを使ってプログラミングするのが新しく、Python 2.7.10を使用してTornado Webサーバーのカスタムデータベースのデータベースインターフェイスを構築しようとしています。しかし、私はBadYieldErrorを得続けます。 tornado.gen.coroutineをPythonのyieldで完全に使用する方法を理解していないのではないかと思います。私は未来を生み出す方法に何か問題があると思う。Python BadYieldError When future yield

これは私のコードです。ここでは、15行目のtestGet関数は外部データベースアクセスのシミュレーションです。

from tornado import gen 
import tornado.ioloop 
import tornado.web 


class MainHandler(tornado.web.RequestHandler): 
    @gen.coroutine 
    def get(self): 
     response = "Hello, world" 
     response = yield db_interface("default", "user_query") 
     self.write(str(response)) 


# meant to demonstrate 
def testGet(query): 
    gen.sleep(2) 
    response = query 
    return response 


@gen.coroutine 
def db_interface(db, key): 
    print str(db) 
    d = yield testGet(key) 
    raise gen.Return(d) 


def make_app(): 
    return tornado.web.Application([ 
     (r"/", MainHandler), 
    ]) 


if __name__ == "__main__": 
    app = make_app() 
    app.listen(8889) 
    tornado.ioloop.IOLoop.current().start() 

出力:

default 
ERROR:tornado.application:Uncaught exception GET/(127.0.0.1) 
HTTPServerRequest(protocol='http', host='127.0.0.1:8889', method='GET', uri='/', version='HTTP/1.1', remote_ip='127.0.0.1', headers={'Accept-Language': 'en-CA,en;q=0.8,fr;q=0.6', 'Accept-Encoding': 'gzip, deflate, sdch', 'Host': '127.0.0.1:8889', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36', 'Dnt': '1', 'Connection': 'keep-alive', 'Cookie': 'ui-auth-127.0.0.1%3A8091=4f1301ef98f1b6fbd80ad059cd5aa2dc', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1'}) 
Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/site-packages/tornado/web.py", line 1415, in _execute 
    result = yield result 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 870, in run 
    value = future.result() 
    File "/usr/local/lib/python2.7/site-packages/tornado/concurrent.py", line 215, in result 
    raise_exc_info(self._exc_info) 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 876, in run 
    yielded = self.gen.throw(*exc_info) 
    File "test.py", line 12, in get 
    response = yield db_interface("default", "user_query") 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 870, in run 
    value = future.result() 
    File "/usr/local/lib/python2.7/site-packages/tornado/concurrent.py", line 215, in result 
    raise_exc_info(self._exc_info) 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 876, in run 
    yielded = self.gen.throw(*exc_info) 
    File "test.py", line 26, in db_interface 
    d = yield testGet(key) 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 870, in run 
    value = future.result() 
    File "/usr/local/lib/python2.7/site-packages/tornado/concurrent.py", line 215, in result 
    raise_exc_info(self._exc_info) 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 956, in handle_yield 
    self.future = convert_yielded(yielded) 
    File "/usr/local/lib/python2.7/site-packages/tornado/gen.py", line 1026, in convert_yielded 
    raise BadYieldError("yielded unknown object %r" % (yielded,)) 
BadYieldError: yielded unknown object 'user_query' 
ERROR:tornado.access:500 GET/(127.0.0.1) 2011.67ms 

私はTornado's official documentation上とthis blog上で適切にこれを行う方法を探すためにしようとしてきたが、私は、私は完全に何を把握することができましたとは思いませんコルーチンの使い方を教えています。

答えて

2

どちらか、それは将来を返すように、このようなコルーチンにtestGetを回す:

@gen.coroutine 
def testGet(query): 
    gen.sleep(2) 
    raise gen.Return(query) 

それとも上yieldを使用しないでください:d = testGet(key)

いずれかを実行すると、コードが機能します。 Futureを返す関数では、yieldを使用する必要があります。

+0

まあ 'testGet'は関数ではなくデータベース呼び出しですので、私はそれをコルーチンに変換できません。収穫関数から得られる方法はありますか?もしそうなら、それは悪い考えだと思いますか? – goatandsheep

+0

私は答えで2つのオプションを与えました:コルーチンに変換するか、 'd = yield testGet(key)'から 'yield'を落としてください。あなたはどちらのオプションの仕事も言っていませんか? – Louis

+0

'testGet'をコルーチンに変換することはできません。なぜなら、それは関数ではなく、デモンストレーション目的で使用している外部呼び出しの表現だからです。 2つ目は動作しますが、なぜですか?未来を表す未来を「収穫」することは可能なのでしょうか?もしそうなら、私はあなたのソリューションが優れていると間違って何をしたのですか? – goatandsheep