[Twisted-Python] Questionaire: How twisted are you ? (Was: Evangelism notes...)

Robin Bryce robin at wiretooth.com
Sun May 8 22:45:33 EDT 2005


In the spirit of just having a go and testing out my twisted knowledge 
on this list I thought I'd start a questionaire, with answers, inspired by:

> I would love to see high level conceptual documentation to give me a
> better idea of  basic concepts  like the "reactor", "application",
> "service", "transport","protocol", "factory" - what they are supposed
> to do and how they are  to fit together.

I am by no stretch of the imagination qualified to advertise these 
answers as authoratative. Buyer beware, and if you don't like mine give 
me a fat -ve 10 for my twisted score and show me your answer ;-)

Authoritative intro material is at:

http://twistedmatrix.com/projects/core/documentation/howto/basics.html
http://twistedmatrix.com/projects/core/documentation/howto/glossary.html

Q1. How do you run a twisted program ?

In as many ways as there are pebbles on a beach ;-)

There are lots of great examples in the docs that get you to the point 
where you have a python file that will create an application instance at 
global scope. Once you've got this far the simplest way to run your 
twisted program is to add the following to that file:

from twisted.internet import reactor
reactor.run()

And then at the command prompt

python myapplication.py

Once you're comfortable with the basics of Services, the Application, 
Factory's and Protocols you're going to start caring about things like 
persistence, daemonization, privilege scheding, plugins etc. At that 
point it's time to look at 'twistd'. If you remove the lines from 
myapplication.py that were added above then you can run your application 
directly from the prompt with:

twistd -oy myapplication.py

Then you will get the almost the same result. The primary difference is 
that your now running your program as a daemon.

twistd is a program that loads twisted applications from many different 
formats, including .py, and starts the application instance it finds there.

Q2. What is an application ?

Most twisted programs begin with an application instance. Twisted 
defines a helper function for creating an application instance so that 
it includes all the bits of functionality that allow it to be driven by 
the twisted framework. This function is found in the module 
twisted.application.service and is called 'Application'.

Most twisted programs define a python file that makes a call to the 
'Application' function at global scope. Just doing this, and nothing 
else, will not get you very interesting results, for that you need to 
look at adding 'Services'.

If you've already got a python file that defines an application instance 
this way - in addition to some example code - and you just want to know 
the simplest way to run your program, then the answer you're after is 
almost certainly:

# add these lines to myprogram.py
from twisted.internet import reactor
reactor.run()

$ python myprogram.py

But see Q1. for a little more on this.

This is the most suitable way if you want to single step through your 
program in a debugger to find out how twisted works. There are many 
other ways to run your program but it's safe to ignore them until you 
decide you want them.

Q3. What's a Service ?

'Services' collect together the bits that make it possible for cool 
networking stuff to happen in a single thread without blocking[1]. You 
don't have to use them to use the twisted framework but they can help. 
If you are using an application instance then you almost certainly want 
to use Services as well.

You add Service's to your application instance (see Q2 for creating 
one). Each service typically manages a discrete network service. The 
twisted framework starts and stops all Services in an application in a 
well defined way when your program is executed. This includes provision 
for giving your services a chance to do stuff before privilege scheding 
happens.

To define what your service is you will usually want to subclass 
twisted.application.service.Service and override any, or all of:

privilegedStartService, startService, stopService.

During a single run of your program each of these methods is called 
exactly once and in exactly that order. If you need to bind to 
privileged ports then privilegedStartService is where you need to do it.

The bits that are used to piece together Service behavior are 
principally: Factory's, Protocols, and Defereds. The parameters involved 
in binding these bits together are things like hostnames, portnumbers, 
database passwords, and (arguably) the networking protocol the service 
is dealing with. Collecting these things together into a service can be 
done by hand, often, it can be easier, more flexible, and much more 
extensible if Adapters are used to do the binding.

[1] Note carefully the word 'possible' in relation to 'without 
blocking'. The twisted framework can not guarantee your program will not 
block. Twisted just gives you a set of concurrency primitives to help 
you write your program so it doesn't block. To understand how to write a 
twisted program so it never blocks you need to learn to love 'Defered's. 
Concurrency primitives in python essentially boil down to a choice 
between callbacks or generators. The twisted framework supports both (as 
of 2.0) but the callback style is the most established. Generators 
didn't arrive   in python until 2.2.

Q4. What's a MultiService ?

At some point you will almost certainly decide that subclassing 
MultiService is going to help you. It's not. To quote moshez:

"duuuuuude. don't. inherit. multiservice."

[And certainly don't inherit from both MultiService and Componentized at 
the same time ;-)]

MultiService is an internal class that is used by the framework to 
manage the order in which all services, added to the application 
instance by you, are started and stoped. The fraze "added to the 
application instance" is potentially misleading but from the birds eye 
perspective this is essentially what you do when you add Services.

You almost certainly do want to subclass Service. But don't be fooled 
into subclassing MultiService.

Q4 What's a Factory ?

Q5 What's a Protocol ?

Q6 How do I get my Factory to open a connection ?

Q7. How do I get my Factory to serve a connection ?

Q8. How do I cancel my attempt to open a connection ?

Q9. What's a plugin ?

Q10. Ok, I'm feeling brave, what is an Application realy and why can't 
it be subclassable ?

You can't subclass it because it is a function. But that doesn't tell 
you anything useful.

The value returned by the function 
twisted.application.service.Appliction is an instance of 
twisted.python.components.Componentized.

Componentized is a class that provides interface aggregation facilities 
in a persistable way. When you call Application you are creating an 
instance of Componentized that aggregates instances of the following 
together:

* twisted.application.service.MultiService
* twisted.application.service.Process
* twisted.persisted.sob.Persitent

The twisted framework uses interfaces and adapters to reduce the 
tendency for functional dependencies to snarl up the implementation of 
the framework. To do this it needs your application to support interface 
aggregation and to provide the basic interfaces that enable it to drive 
your program the Twisted way.

In these terms the function Application produces an instance that 
supports the interfaces IService, IMultiService, IPersitable and 
IProcess. MultiService implements IService and IMultiService[1], 
Persistent implements IPersistable, and Process implements IProcess.

These are the basic guarantees about the application instance that 
enable the twisted framework to drive your application.

You can't specialize of the above instances either - unless you are 
prepared to mimic the behavior of Application. You're only route for 
specializing your application is by adding services. ie., via some 
variation of:

IService(MySerivce()).setServiceParent(IMultiService(application))


It's not unusual or unreasonable to write a replacement for Application. 
A perfectly acceptable example is:

def MyApplication():

       a = MyService()
       a.setName("myapplication")
       ret = service.MultiService()
       a.setServiceParent(ret)

       return ret

Reading up on adapters & interfaces in the python / Zope3 sense can give 
you an extra perspective when looking at the twisted docs on Adapters 
and interfaces. Twisted 2.0 actually uses Zope3 interfaces. And if 
you're reading this answer then there is a good chance taking the time 
to do this will help you.

http://www.python.org/peps/pep-0246.html
http://mail.zope.org/pipermail/zope3-dev/2005-January/013064.html

[1]It is required that the IService interface and the IMultiService 
interface are implemented by the same underlying object (or at least it 
is by the application unit tests).

You really probably don't want to read any more of this answer. For one 
thing Componentized looks like it's going to be superseded by Faceted 
which does similar things but much much better.

 From the doc string of Componentized:

"I am a mixin to allow you to be adapted in various ways persistently."

Componentized caches addaptions in a persitable way. Your applications 
root service, the MultiService instance above is effectively a 
persistably cached adaption from None to IMultiService and to IService.

Well you did ask ;->

When you do:

IService(application)

You are retreiving the IService interface for you application that 
happens to be implemented by twisted.application.service.MultiService

Depending on the feedback I'm keen to see/provide answers to Q4-Q8, 
Don't feel confident at all about Q9.

Cheers,

Robin

Mary Gardiner wrote:
> On Sun, May 08, 2005, Eugene Coetzee wrote:
> 
>>It certainly helps, although it may be a bit minimalistic. 
> 
> 
> A review would be appreciated :) Also, any suggestions on how to make
> the glossary easier to find? 
> 
> -Mary
> 
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python




More information about the Twisted-Python mailing list