Search code examples
pythontornado

how to yield gen.coroutine methods


I'm running a Tornado server with the following class:

class SessionHandler(tornado.websocket.WebSocketHandler):
   def open(self):
      pass

   def on_close(self):
      pass

   @tornado.gen.coroutine
   def on_message(self,message):
      #db added to the tornado application object on init
      self.application.db.add("test")
      x=self.application.db.get("test")
      print(x)

The get function are follows (part of the db class):

   @tornado.gen.coroutine
   def get(self,key):
      result=[]
      lookup=yield self.postCol.find_one({"_id":key})

      if not lookup:
         return result

      for id in lookup["FieldArray"]:
         ob=yield self.postCol.find_one({"_id":ObjectId(id)})
         result.append(ob)
      return result

I won't type the add() function out.

I realized that the get() returns a Future object instead of the array. That's fine, I realize I need to change my code to x = yield self.application.db.get("test").

My question is the add() function has no explicit return value in my method?

Do I still need to yield that when I call it too I.e. yield self.application.db.add("test")?

It does currently work without my yielding, however I'm wondering if it's a mistake not to yield, because I know it does return a Future object?

If that's the case, does that mean I basically have to yield any method I call that is decorated with gen.coroutine?


Solution

  • Yes, you should "yield" any call to a coroutine. There are two reasons:

    1. If you don't yield, then the coroutine is spawned and runs concurrently with the calling coroutine. You probably want to wait for "add" to finish before executing the next statement in "on_message"? The only way to make "on_message" wait for "add" to complete is to yield the Future returned by "add".
    2. If "add" throws an exception--for example if your network connection to the database fails, or if your document is invalid or violates a unique index--the only way to know that an exception was thrown is to yield the Future returned by "add". Otherwise the exception is silently ignored, see the big warning in Tornado's coroutine documentation.