2014-11-20 24 views
11

Tornado coroutines'i öğrenmeye çalışıyorum, ancak aşağıdaki kodu kullanarak hatam var.Tornado coroutine

Traceback (most recent call last): 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\web.py", line 1334, in _execute 
    result = yield result 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run 
    value = future.result() 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 109, in result 
    raise_exc_info(self._exc_info) 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 631, in run 
    yielded = self.gen.throw(*sys.exc_info()) 
    File "index.py", line 20, in get 
    x = yield 'test' 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\gen.py", line 628, in run 
    value = future.result() 
    File "D:\projekty\tornado\env\lib\site-packages\tornado\concurrent.py", line 111, in result 
    raise self._exception 
BadYieldError: yielded unknown object 'test' 

Kodu:

from tornado.ioloop import IOLoop 
from tornado.web import RequestHandler, Application, url 
from tornado import gen 

class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield 'test' 
     self.render('hello.html') 


def make_app(): 
    return Application(
     [url(r"/", HelloHandler)], 
     debug = True 
    ) 

def main(): 
    app = make_app() 
    app.listen(8888) 
    IOLoop.instance().start() 

main() 
+0

x = verim 'sınaması' satırında ne yapmaya çalışıyorsunuz? –

+0

sadece bir örnek, bir fonksiyonun sonucunu vermeyi denedim - sonuç aynı, bu satır sadece coroutines'i test etmek için – klis87

cevap

26

Lutz Horn'un işaret ettiği gibi, tornado.coroutine dekoratör, yalnızca Future nesnelerini veya Future nesneleri içeren belirli kapları vermenizi gerektirir. Yani bir str vermeyi denemek bir hata verecektir. Kaybettiğiniz parçanın, yield something(), something'u aramak istediğiniz bir koroutinin içindeki herhangi bir yerin de bir coroutine olması ya da Future'u iade etmesi gerektiğini düşünüyorum. Örneğin, bu gibi örneğin sorununu gidermek olabilir: Hatta bu

from tornado.gen import Return 

class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield self.do_test() 
     self.render('hello.html') 

    @gen.coroutine 
    def do_test(self): 
     raise Return('test') 
     # return 'test' # Python 3.3+ 

Ya (genellikle bu şekilde yapmaması gereken gerçi):

Tabii
class HelloHandler(RequestHandler): 
    @gen.coroutine 
    def get(self): 
     x = yield self.do_test() 
     self.render('hello.html') 

    def do_test(self): 
     fut = Future() 
     fut.set_result("test") 
     return fut 

, bu yapmacık örneklerdir; Aslında do_test'da asenkronize bir şey yapmadığımızdan, onu bir koroutin yapmak için bir sebep yok. Normalde orada bir tür asenkronize I/O yapıyor olacaksınız. Örneğin,

+0

uygulamak Büyük bir teşekkür için teşekkürler, do_test işlevinin başında time.sleep ekledim ve her şey gibi çalışır eşzamanlı kodda, self.render (x) bittikten sonra yürütüldüğümde, belki de bu fonksiyonun arka planda gerçekleştirildiğini düşündüm, durum böyle değil ... Daha sonra koroutinler kullanmanın yararı nedir? Belki başka bir kullanıcı önceki kullanıcının uyku bitmeden aynı anda bağlantıyı açabilir? – klis87

+2

@ user3575996 Verim işlevi() 'işlevi,' function() 'tamamlanıncaya kadar beklemenin yürütülmesini koordine edecektir. Ancak, kasırga I/O döngüsünü * engellemeyecektir *, bu nedenle istemcilerden gelen diğer istekler geldiğinde, bunlar aynı zamanda ele alınabilir. Ancak, bunu engellemek için 'time.sleep()' işlevini kullanamazsınız, çünkü bu bir engelleme işlevidir. Engelleme olmayan bir uyku sürümü kullanmanız gerekir. Bir örnek için [bu yanıt] 'a bakın (http://stackoverflow.com/a/23876402/2073595). – dano

+0

Şimdilik teşekkürler Nihayet herşeyi anlıyorum :) – klis87

3

From the documentation: Tornado

En asenkron fonksiyonlar dönmek bir Future; Bu nesneyi elde etmek sonucunu verir.

Aynı zamanda başlatılacak ve paralel olarak çalışacak olan yield a list or dict of Futures; hepsi bittiğinde bir liste veya sonuçların dict iade edilecektir:

dize "test" bir Future değildir. Bir tane vermeyi dene.

+2

Veri tabanı sorgusunun sonucunu vermek istiyorum, get_all_users() fonksiyonunun bunu yapmasını söyleyelim bana örnek verebilir misiniz kasırga örneklerini kullanmak gibi bazı yerleşik sınıfları kullanmak AsyncHTTPClient(), nasıl kendi – klis87

İlgili konular