Unfortunately this article did nothing to enlighten me - it has some pretensions of being philosophical without explaining any of the practicalities.
Does anyone use Twisted in production? Do you consider it worth the learning curve, and would you use it again if you were implementing your system now?
I struggled with twisted several times without getting it. Then I did some non-blocking socket/select programming and thought, "I wish I had a library that.." and then realised what twisted did.
There's a few reasons I'm not using it now. Main one is that I've turned against frameworks. I find it's generally easier to understand a problem and write the code than to really learn a generic framework and coax it to your needs. And by just writing the code yourself you don't have to deal with dependencies, you have more freedom to make changes, debugging is easier, it's easy to deploy in a restricted environment.
Also, I have a rule of thumb when I'm writing python that if I'm using inheritance I'm doing something wrong. I have huge trouble understanding duck-type code that uses inheritance. Encapsulation is always possible, and I find it a lot easier to refactor. Twisted uses inheritance extensively. The docs encourage you to extend their classes. In places the application developer is expected to reach into framework objects and poke variables.
It's interesting that inheritance vs composition comes up, since one of the most common criticisms I've heard is actually the opposite (that there's too many different objects to get things done).
However, I do understand why you might think this: protocols, which is probably the first thing you touch in Twisted, are usually implemented through inheritance. For resources, the default implementation that you subclass (twisted.web.resource.Resource) contains a bunch of behavior that you almost certainly want.
The important thing to remember is that this inheritance is only to get default behavior. If you want to implement it without inheritance, Twisted very clearly and explicitly defines the interface you have to implement:
These are just two examples: Interfaces are all over twisted.
And, to quote from the article:
It doesn't need to be that way, though. When you create
an object, it is best to create it as independently as
possible; to test it in isolation; to discretely separate
its every interaction with the outside world so that they
may be carefully controlled, monitored, intercepted an
inspected, one iteration at a time.
I'm impressed with the achievement of Twisted. For example, the way it offers support for both unix-way async (select, getabyte getabyte), and the Windows/AIX alternative where you can make a system call that says "get back to me when you have a complete message that I can consume in one hit". It'll be way faster and more polished than the stuff I write too.
Part of the reason there's so many objects in it is because it does so damn much - there's support for all sorts of existing protocols in twisted. And - a powerful framework can't entirely abstract away the layering. If it does, it stops being powerful.
It might be possible to use virutalenvs. I keep meaning to look into these. I am skeptical of frameworks though. You become vulnerable to version changes, you can't take knowledge to a new platform.
Very interested to see something from the python-ideas conversation in the standard library. I'll have a serious go at whatever they end up with, and wouldn't mind if it was a stripped down twisted but with composition rather than inheritance. It may be the feature that pushes python people to v3. I'll look over the links you sent regarding this.
I'm curious because Twisted has been around for ages and seems to be in active development but I've never talked to anyone who actually uses it.
Lucasfilm, justin.tv, Launchpad and TweetDeck are some of the larger names you may have heard of. A bunch of smaller startups do too.
If you've been doing XMPP you've probably used a Twisted server (it's either that or ejabberd, mostly) at some point.
If you want Tornado, why not use Cyclone? It's a port (to Twisted) of Tornado; you get to write webby parts just like tornado's and you get the benefit of all of Twisted when you need it.
FWIW, I did the Twisted Help Desk and co-hosted the Twisted tutorial two years in a row now at EuroPython, and two years in a row that tutorial has had to move to a bigger room. Asking around showed a large portion of people were there because there place of work was either using or considering using Twisted. I never cease to be surprised by the stories I hear of people using Twisted to great success for pretty nifty applications.
That's an awful excuse. People rely on libraries in order to do their jobs. A "worse" library with better documentation helps more people.
The fact that Twisted advocates have to keep browbeating others to accept it is just one indication that it's not perfect and it's not for everyone.
It's certainly a difficult thing to get your head around. The parts of the project that touch twisted is always the most complex to explain to anyone else. However, async code is always hard. It also doesn't help that the code base shows it's age.. non-PEP8, strange naming conventions etc.
However, one thing that I've noticed with recent projects using Tornado (https://github.com/rhettg/Dynochemy) is that some concepts that I thought was overly complex in Twisted makes sense eventually. For example, handling errors in async code is really hard. The framework twisted came up with with Deferred, callbacks and errbacks is pretty smart. You almost have to re-invent twisted before you can appreciate it.
I'd recommend reading the original paper for more information: http://www6.uniovi.es/python/pycon/papers/deferex/
I am currently not using Twisted for anything, but often think that things I'm currently working on would be easier if done in Twisted.
I came to Twisted after 5 years of doing non-blocking servers in C with libevent (or hand rolled event loops). So I didn't have to wrap my head around don't call us, we'll call you aspect. I'm currently using Tornado for a websocket based service, but will probably use Twisted again for my next Python project.
1) The documentation is terrible.
Even though there's a lot of it, and even though the API documentation is pretty good, the 'narrative' and tutorial-like documentation is downright horrible. It tries to cram so many things into the same contrived examples at once, that reading it creates more confusion than giving insights. Take for example the 'evolution of a finger client', which is one of the first things you get directed to when you want to start 'learning twisted'. Instead of introducing some basic concepts that affect design decisions and then working them out in simple, individual, small examples, it starts out with a server example so trivial that it's completely un-representative of how a typical Twisted service would look like, and then, in a few pages, crams so many things into it at once that you have to go back, re-read and actually try to implement and run the example yourself to figure out what (and especially: why) the heck things are working like they are working. In one swell swoop it 'teaches' you Twisted by throwing around component-based programming, Zope interfaces, adapter classes, the factory pattern and how you can basically use it everywhere even though there's no real reason to do so, how you can expose 4 different protocols talking to the same service at once, how you can add asynchronous versions of the same services, and so on. All of it combined in a single 'Twisted application' that reads like some kind of intentially obfuscated crypto-program that somehow magically does all these things.
Compare to that the Pyramid documentation, which is absolutely fantastic and got me up to speed and writing very clean and stable applications in just a few hours. Where reading the Twisted docs the main thing going around in my head was 'wtf do I have to do here and why', while with Pyramid it everything immediately made sense. Note that I'm not saying this is a problem with Twisted itself, just with the way the documentation tries to explain how to use it.
2) Twisted doesn't advertise its specific benefits and downsides very well.
Superficially looking, many people might think Twisted is just like other web-application frameworks like Pyramid, Flask or Django, but it isn't. You can do most of everything using Twisted, but it's much lower-level than those. Just like this article mentions, Twisted is more like a toolbox to create event-based applications than it is like a web-app framework. This makes it a lot more flexible, but also more complex. While this allows all kinds of use cases that nobody would ever consider e.g. something like Flask or Django for (e.g. game servers, chat servers, etc), it also means that if your application is 'yet another web application', the other options are probably going to be a lot simpler and cleaner than using Twisted.
I think because Twisted doesn't want to choose and declare what it's main strengths and purposes are, it's attracting many developers of applications that are a much better fit for the more specialized web-app frameworks, leaving them with a really bad experience, spending too much time figuring out the framework and ending up with cryptic gibberish that doesn't really implement any actual application logic.
Don't misinterpret this as a critique of Twisted itself, I still like it a lot, exactly because it is so flexible and generic. It's just not the best tool for most web applications, but if if you are implementing some kind of event-based application that doesn't fit the philosophy of the other popular frameworks, it's extremely powerful and well-designed. I think the Twisted community should make this difference more explicit for new developers.
Problem: bicycle seats are hard. They hurt.
Analysis: there must be something wrong with your pants.
"Solution": dorky pants.
Problem: Python has poor support for threads, and concurrency in general.
Analysis: you must need more middleware.
"Solution": incomprehensible callback-based frameworks.
#1 In python specifically, we do not have proper closure and no anonymous blocks, this makes operating it tedious as the definition of the logic for a callback is always somewhere else from where the callback is setup.
I intently dislike twisted and node.js for these very reasons. I've written my own little framework based entirely on greenlets in python, which is delightful and easy to use and entirely avoids both dislocality of action and the pyramid of death.
Also, does @inlineCallbacks address your issue? The only fundamental difference I see (other than implementation nastiness, which I guess both have some issue with :)) is that with inlineCallbacks your yields are explicit, and with greenlets they're not.
Twisted feels to me like a grand experiment that's groping towards something that we know is there, but not quite catching it yet. I guess I/O monads feel like slightly further along the path - but they're still not the true solution. What does your system look like?
In IO frameworks that are greenlet based, the greenlet is resumed when it has stuff waiting for it.
The obvious difference to the programmer is that a greenlet won't have yield statements in them, whereas a generator would.
What impact do you feel the destruction of locality has, specifically?
Do you feel @inlineCallbacks and Corotwine answer these issues?
My understanding of Corotwine and greenlet is that they're basically poor man's threads. Basically, if the language doesn't give you usable threads, you can go ahead and implement your own. I've done that one too-- I once wrote an M:N threading library in userspace. Basically making a small number of kernel threads look like a large number of threads to the programmer.
The problem with rolling your own threads is that the normal tooling that comes with the language won't know how to handle what you built. There is no syntax for your add-on, and the semantics may be murky at best. Stack traces become useless, and error messages become guru meditations. Interfacing with third party libraries becomes a challenge, unless they're designed to be purely single threaded.
Additionally-- how to put this delicately? Something as fundamental as threads should not be built as an add-on to a programming language. Things built on top of a language tend to be very fragile and buggy compared to things built in to a language. The C programming language was designed before threads were even a thing in UNIX, so lacking threads was understandable. We built our own threading packages because we had to. But you shouldn't need to do that for a modern language.
This will certainly improve the situation with interfacing different Python libraries together if it gets adopted. I still don't think asynchronous APIs are as easy to use as blocking ones, but I guess I've said enough about that already :)