@tornado.gen.engine and @tornado.web.asynchronous

361 views
Skip to first unread message

Nick Baum

unread,
Apr 11, 2013, 6:47:24 PM4/11/13
to python-...@googlegroups.com
The docs specify that I need to include both @tornado.gen.engine and @tornado.web.asynchronous for async handlers that use gen.

However, my code seems to work just fine with just the @tornado.gen.engine decorator. There are no duplicate calls to self.finish, and I don't have to call finish manually.

Am I missing something? Are there edge cases where it will break?

-Nick

aliane abdelouahab

unread,
Apr 11, 2013, 8:17:47 PM4/11/13
to Tornado Web Server
about self.finish():
it is called when you do self.render() or self.redirect()
but if you just make something that dont use those two, you will have
a browser turning untill giving an error like the server dont work,
this is where you must call self.finish() explicitly.

aliane abdelouahab

unread,
Apr 11, 2013, 8:20:40 PM4/11/13
to Tornado Web Server
as an example where you must use self.finish():
self.write() this one if you use it, your browser will hang! you must
call explicitly self.finish() after self.write()
for the first question, hope someone else can help, i think i saw the
answer but dont remember where.

On 11 avr, 23:47, Nick Baum <nickb...@whereberry.com> wrote:

aliane abdelouahab

unread,
Apr 11, 2013, 8:27:34 PM4/11/13
to Tornado Web Server

Ben Darnell

unread,
Apr 11, 2013, 8:59:17 PM4/11/13
to Tornado Mailing List
Aliane is right; if a handler method uses @gen.engine you need to also use @asynchronous (at least as long as the generator yields anything interesting).  @gen.coroutine is a little more magic:  as of 3.0.1 if you use both @asynchronous and @gen.coroutine you don't have to call finish() explicitly (this isn't documented because it was a side effect of the 3.0.1 patch and wasn't in 3.0). In 3.1 I think you'll be able to use @gen.coroutine without @asynchronous, as well as use @gen.coroutine on methods that cannot currently be made asynchronous like prepare().

-Ben 


On Thu, Apr 11, 2013 at 8:27 PM, aliane abdelouahab <alabde...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornad...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



aliane abdelouahab

unread,
Apr 11, 2013, 9:10:25 PM4/11/13
to Tornado Web Server
thank you for the explications :)

On 12 avr, 01:59, Ben Darnell <b...@bendarnell.com> wrote:
> Aliane is right; if a handler method uses @gen.engine you need to also use
> @asynchronous (at least as long as the generator yields anything
> interesting).  @gen.coroutine is a little more magic:  as of 3.0.1 if you
> use both @asynchronous and @gen.coroutine you don't have to call finish()
> explicitly (this isn't documented because it was a side effect of the 3.0.1
> patch and wasn't in 3.0). In 3.1 I think you'll be able to use
> @gen.coroutine without @asynchronous, as well as use @gen.coroutine on
> methods that cannot currently be made asynchronous like prepare().
>
> -Ben
>
> On Thu, Apr 11, 2013 at 8:27 PM, aliane abdelouahab <alabdeloua...@gmail.com
>
>
>
>
>
>
>
> > wrote:
> > got it, here is  the thread:
>
> >https://groups.google.com/group/python-tornado/browse_thread/thread/a...

Nick Baum (StoryWorth)

unread,
Apr 11, 2013, 9:16:57 PM4/11/13
to Tornado
Thanks Aliane and Ben, I'm still not sure I understand though.

Let's say my handler looks like this:

@tornado.gen.engine
def post(self)
    url = yield tornado.gen.Task(self.process_post)
    self.redirect(url)

def process_post(self, callback)
    ...
    callback(url)

Do I need to decorate the post method with @tornado.web.asynchronous, and if so, why?

-Nick



--
You received this message because you are subscribed to a topic in the Google Groups "Tornado Web Server" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python-tornado/7ELZz6H7TK8/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to python-tornad...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.





--
Nick Baum
StoryWorth.com Founder

aliane abdelouahab

unread,
Apr 11, 2013, 9:23:34 PM4/11/13
to Tornado Web Server
when you call a decorator, here is what you do:
http://stackoverflow.com/questions/739654/understanding-python-decorators/1594484#1594484
so you are modifying this:
https://github.com/facebook/tornado/blob/master/tornado/web.py#L1149

On 12 avr, 02:16, "Nick Baum (StoryWorth)" <n...@storyworth.com>
wrote:
> Thanks Aliane and Ben, I'm still not sure I understand though.
>
> Let's say my handler looks like this:
>
> @tornado.gen.engine
> def post(self)
>     url = yield tornado.gen.Task(self.process_post)
>     self.redirect(url)
>
> def process_post(self, callback)
>     ...
>     callback(url)
>
> Do I need to decorate the post method with @tornado.web.asynchronous, and
> if so, why?
>
> -Nick
>
> On Thu, Apr 11, 2013 at 6:10 PM, aliane abdelouahab <alabdeloua...@gmail.com
> >https://groups.google.com/d/topic/python-tornado/7ELZz6H7TK8/unsubscr...
> > .
> > To unsubscribe from this group and all its topics, send an email to
> > python-tornad...@googlegroups.com.
> > For more options, visithttps://groups.google.com/groups/opt_out.

Ben Darnell

unread,
Apr 11, 2013, 9:33:41 PM4/11/13
to Tornado Mailing List
On Thu, Apr 11, 2013 at 9:16 PM, Nick Baum (StoryWorth) <ni...@storyworth.com> wrote:
Thanks Aliane and Ben, I'm still not sure I understand though.

Let's say my handler looks like this:

@tornado.gen.engine
def post(self)
    url = yield tornado.gen.Task(self.process_post)
    self.redirect(url)

def process_post(self, callback)
    ...
    callback(url)

Do I need to decorate the post method with @tornado.web.asynchronous, and if so, why?

Depends on what process_post does.  If it runs straight through and runs the callback immediately, then you may not need @asynchronous (and in that case you're not gaining anything by making it take a callback and calling it with gen.Task).  If it runs the callback asynchronously (e.g. if process_post also has @gen.engine and yields something), then you definitely need @asynchronous on post().  Without @asynchronous, the post may return an empty 200 to the client before reaching the redirect.

-Ben

Nick Baum (StoryWorth)

unread,
Apr 12, 2013, 2:09:31 PM4/12/13
to Tornado
Ah, I get it. The reason my handlers worked without the @asynchronous decorator is that the only ones that were doing asynchronous work didn't actually need to return any content to the browser (they could essentially call finish right away).

So in fact it was an edge case that it actually worked!

Thanks for the explanations.

-Nick
Reply all
Reply to author
Forward
0 new messages