yield f1()
yield f2()
You force f1 to finish before being able to start f2, which goes against the whole point of using something like twisted in the first place ! I have also noticed that inlineCallback screw up the traceback (e.g. http://twistedmatrix.com/trac/ticket/3622 - I still see this with twisted 10.0.0).While I am no genius, I am a decent programmer, with quite a few years of experience in python, and I still can't read most non trivial async code in twisted with confidence. It is almost impossible IMO to get a clear idea of the codeflows and especially error flows to ensure error handling is done right. Error handling is already difficult as is, adding exception made it that much harder, but adding async makes it basically impossible except for Vulcans.
inlineCallbacks allows you to write code in a synchronous manner (that's the point). If you'd like to wait for completion of both f1 and f2 functions simultaneously you could:
yield DeferredList([f1(), f2()])
The ticket you mentioned is closed as invalid. Use `failure.printTraceback()`.Non trivial async code is hard to read (period).
Exceptions allows you deal with errors in the place where you know what to do with them, not in the place where they arise (as in any other Python code).
Using deferred lists is a fair point, but then you are kind of back to using deferred directly.
As for tracebacks, I used the ticket as an example: if you have to use failure.printTraceback, it means you caught the exception, which means you need to catch them everywhere. But the problem is when there is a big in your application because you forget to handle an exception - debugging those is a PITA because you don't get the right traceback.
So yeah, async code is hard, inlineCallback sometimes helps, but all this really feel like a big kludge to me - I would rather use a framework where async is abstracted away. Doing all this by hand does not work very well for complex applications.