[Twisted-Python] Inline Callbacks

Would it be fair to say that when developing code that utilizes inlineCallbacks, your function is a generator that returns a deferred whose callback is the coroutine that's yielding? -J

On Thu, Apr 1, 2010 at 8:20 PM, Jason J. W. Williams <jasonjwwilliams@gmail.com> wrote:
It pays to be very very specific about all the different objects and interactions going on with generators in Python and especially with inlineCallbacks to avoid confusion.There are a couple of inaccuracies in this statement, some which I think are just about poor wording and some which come from misunderstanding. In Python, there are generator functions and there are generators. Calling a generator function returns a generator, which has next() and send() methods. Generators do not return things, though a generator's next() or send() methods do (I say this because you mentioned a "generator that returns a deferred"). Also, there's nothing called a "coroutine" that's related to inlineCallbacks at all, and the word is fraught with ambiguities in Python, so it's best to just avoid it entirely. In inlineCallbacks, nobody but the person writing the inlineCallbacks-using function knows that there's a generator involved. The person calling your inlineCallbacks-using function can't see any generators; they just get a Deferred object which fires when the generator is exhausted. The interesting part is that inlineCallbacks is the thing responsible for iterating the generator, not user-code. It is responsible for calling .send() on the generator object when previously yielded deferreds have fired. The value of the Deferred returned will be whatever is passed to returnValue in the inlineCallbacks-using function. -- Christopher Armstrong http://radix.twistedmatrix.com/ http://planet-if.com/

Hi Christopher, Apologize for the sloppy language. So would this be a better way of putting it? Assuming a function func_a that has the inlineCallbacks decorator... If func_a were added as a callback for a deferred (deferred 1), when func_a was called another deferred would be returned (deferred 2) which would only fire once func_a had run to the end of the function and returned. While func_a is running, every time yield is called, this would operate similarly to writing a separate callback for the contents of each of those yield statements and chaining them normally to each other as callbacks. That is this: @defer.inlineCallbacks def func_a(value): num = yield do_something(value) num2 = yield do_something_more(num) return num2 is equivalent to: def func_a(value): return do_something(value).addCallback(cb_step_1) def cb_step_1(num): return do_something_more(num).addCallback(cb_step_2) def cb_step_2(num2): return num2 Thank you very much for your help in understanding this. I've always used a combination of deferreds and callbacks/errbacks to this point. -J On Thu, Apr 1, 2010 at 10:33 PM, Christopher Armstrong <radix@twistedmatrix.com> wrote:

On Thu, Apr 1, 2010 at 8:20 PM, Jason J. W. Williams <jasonjwwilliams@gmail.com> wrote:
It pays to be very very specific about all the different objects and interactions going on with generators in Python and especially with inlineCallbacks to avoid confusion.There are a couple of inaccuracies in this statement, some which I think are just about poor wording and some which come from misunderstanding. In Python, there are generator functions and there are generators. Calling a generator function returns a generator, which has next() and send() methods. Generators do not return things, though a generator's next() or send() methods do (I say this because you mentioned a "generator that returns a deferred"). Also, there's nothing called a "coroutine" that's related to inlineCallbacks at all, and the word is fraught with ambiguities in Python, so it's best to just avoid it entirely. In inlineCallbacks, nobody but the person writing the inlineCallbacks-using function knows that there's a generator involved. The person calling your inlineCallbacks-using function can't see any generators; they just get a Deferred object which fires when the generator is exhausted. The interesting part is that inlineCallbacks is the thing responsible for iterating the generator, not user-code. It is responsible for calling .send() on the generator object when previously yielded deferreds have fired. The value of the Deferred returned will be whatever is passed to returnValue in the inlineCallbacks-using function. -- Christopher Armstrong http://radix.twistedmatrix.com/ http://planet-if.com/

Hi Christopher, Apologize for the sloppy language. So would this be a better way of putting it? Assuming a function func_a that has the inlineCallbacks decorator... If func_a were added as a callback for a deferred (deferred 1), when func_a was called another deferred would be returned (deferred 2) which would only fire once func_a had run to the end of the function and returned. While func_a is running, every time yield is called, this would operate similarly to writing a separate callback for the contents of each of those yield statements and chaining them normally to each other as callbacks. That is this: @defer.inlineCallbacks def func_a(value): num = yield do_something(value) num2 = yield do_something_more(num) return num2 is equivalent to: def func_a(value): return do_something(value).addCallback(cb_step_1) def cb_step_1(num): return do_something_more(num).addCallback(cb_step_2) def cb_step_2(num2): return num2 Thank you very much for your help in understanding this. I've always used a combination of deferreds and callbacks/errbacks to this point. -J On Thu, Apr 1, 2010 at 10:33 PM, Christopher Armstrong <radix@twistedmatrix.com> wrote:
participants (2)
-
Christopher Armstrong
-
Jason J. W. Williams