Twisted?
Please see Twisted
gettingTwisted.
Did you check the HOWTO collection? There are so many documents there that they might overwhelm you... try starting from the index, reading through the overviews and seeing if there seems to be a chapter which explains what you need to. You can try reading the PostScript or PDF formatted books, inside the distribution. And, remember, the source will be with you... always.
Twisted is a lot of things, rolled into one big package. We're not sure if it'll stay this way, yet, but for now, if you have only specific needs, we recommend grabbing the big Twisted tarball, and if you want, you can run the 'setup.py' script with a modified config file to generate a package with only certain Twisted sub-packages. Twisted as a whole makes it into many operating system distributions (FreeBSD, Debian and Gentoo, at least) so size shouldn't be an issue for the end developer or user. In addition, packaging Twisted as a whole makes sure the end users do not have to worry about versioning parts of Twisted and inter-version compatibility.
If you are distributing Twisted to end-users, you can base your distribution
on the Nodocs
packages, which are signficantly smaller.
No. You only need to import the sub-packages which you want to use, meaning only those will be loaded into memory. So if you write a low-level network protocol, you'd only import twisted.internet, leaving out extraneous things like twisted.web, etc. Twisted itself is very careful with internal dependancies, so importing one subpackage is not likely to import the whole twisted package.
No, only specific parts of Twisted are stable, i.e. we only promise backwards compatibility for some parts of Twisted. While these APIs may be extended, they will not change in ways that break existing code that uses them.
While other parts of Twisted are not stable, we will however do our best to make sure that there is backwards compatibility for these parts as well. In general, the more the module or package are used, and the closer they are to being feature complete, the more we will concentrate on providing backwards compatibility when API changes take place.
Only modules explictily marked as such can be considered stable. Semi-stable modules may change, but not in a large way and some sort of backwards-compatibily will probably be provided. If no comment about API stability is present, assume the module is unstable.
In Twisted 1.1, most of twisted.internet, .cred and .application are completely stable (excepting of course code marked as deprecated).
But as always, the only accurate way of knowing a module's stability is reading the module's docstrings.
Don't run scripts out of site-packages
. The Windows
installer should install executable scripts to someplace like
C:\Python22\scripts\
, *nix installers put them in
$PREFIX/bin
, which should be in your $PATH.
An example: 1.0.6+1.0.7rc1-1
In Debian versioning, 1.0.7rc1 is greater than 1.0.7. This means that if you install a package with Version: 1.0.7rc1, and then that package gets a new version 1.0.7, apt will not upgrade it for you, because 1.0.7 looks like an older version. So, we prefix the previous version to the actual version. 1.0.6+1.0.7rc1 is less than 1.0.7.
You can't. A Protocol doesn't have a Factory when it is created. Instead,
you should probably be doing that in your Protocol's
connectionMade
method.
Similarly you shouldn't be doing real
work, like connecting to
databases, in a Factory's __init__
either. Instead, do that in
startFactory
.
See Writing Servers and Writing Clients for more details.
Try Writing Servers.
Here's the rule - installing a reactor should always be the first thing you do, and I do mean first. Importing other stuff before you install the reactor can break your code.
Tkinter and wxPython support, as they do not install a new reactor, can be done at any point, IIRC.
twistd
won't load my .tap
file! What's this
Ephemeral nonsense?When the pickled application state cannot be loaded for some reason, it is common to get a rather opaque error like so:
% twistd -f test2.tap Failed to load application: global name 'initRun' is not defined
The rest of the error will try to explain how to solve this problem,
but a short comment first: this error is indeed terse -- but there is
probably more data available elsewhere -- namely, the twistd.log
file. Open it up to see the full exception.
The error might also look like this:
Failed to load application: <twisted.persisted.styles.Ephemeral instance at 0x82450a4> is not safe for unpickling
To load a .tap
file, as with any unpickling operation, all
the classes used by all the objects inside it must be accessible at the time
of the reload. This may require the PYTHONPATH variable to have the same
directories as were available when the application was first pickled.
A common problem occurs in single-file programs which define a few
classes, then create instances of those classes for use in a server of some
sort. If the class is used directly, the name of the class will be recorded
in the .tap
file as something like
__main__.MyProtocol
. When the application is reloaded, it will
look for the class definition in __main__
, which probably won't
have it. The unpickling routines need to know the module name, and therefore
the source file, from which the class definition can be loaded.
The way to fix this is to import the class from the same source file that
defines it: if your source file is called myprogram.py
and
defines a class called MyProtocol
, you will need to do a
from myprogram import MyProtocol
before (and in the same
namespace as) the code that references the MyProtocol class. This makes it
important to write the module cleanly: doing an import
myprogram
should only define classes, and should not cause any other
subroutines to get run. All the code that builds the Application and saves
it out to a .tap
file must be inside an if __name__ ==
'__main__'
clause to make sure it is not run twice (or more).
When you import the class from the module using an external
name,
that name will be recorded in the pickled .tap
file. When the
.tap
is reloaded by twistd
, it will look for
myprogram.py
to provide the definition of
MyProtocol
.
Here is a short example of this technique:
# file dummy.py from twisted.internet import protocol class Dummy(protocol.Protocol): pass if __name__ == '__main__': from twisted.application import service, internet a = service.Application("dummy") import dummy f = protocol.Factory() f.protocol = dummy.Dummy # Note! Not "Dummy" internet.TCPServer(2000, f).setServiceParent(service.IServiceCollect(a)) a.save()
Interrupted system callerrors when I use
os.popen2
. How do I read results from a sub-process in
Twisted?You should be using reactor.spawnProcess
(see
interfaces.IReactorProcess.spawnProcess
).
There's also a convenience function, getProcessOutput
, in twisted.internet.utils
.
spawnProcess
defaults to clearing the environment of child processes as a security
feature. You can either provide a dictionary with exactly the name-value
pairs you want the child to use, or you can simply pass in
os.environ
to inherit the complete environment.
It really depends on what your program is doing, but the most common cause is this: it is firing -- but it's an error, not a success, and you have forgotten to add an errback, so nothing happens. Always add errbacks!
The reason this happens is that unhandled errors in Deferreds get printed
when the Deferred is garbage collected. Make sure your Deferred is garbage
collected by deleting all references to it when you are done with it, e.g.
after callback()
is called.
See previous question.
You don't. Deferreds don't magically turn a blocking function call into a non-blocking one. A Deferred is just a simple object that represents a deferred result, with methods to allow convenient adding of callbacks. (This is a common misunderstanding; suggestions on how to make this clearer in the Deferred Execution howto are welcome!)
If you have blocking code that you want to use non-blockingly in Twisted,
either rewrite it to be non-blocking, or run it in a thread. There is a
convenience function, deferToThread
, to help you with the
threaded approach -- but be sure to read Using
Threads in Twisted.
exceptions.ValueError: signal only works in main threadwhen I try to run my Twisted program! What's wrong?
The default reactor, by default, will install signal handlers to catch
events like Ctrl-C, SIGTERM, and so on. However, you can't install signal
handlers from non-main threads in Python, which means that
reactor.run()
will cause an
error. Pass the installSignalHandlers=0
keyword argument to
reactor.run
(or Application.run
) to work around
this.
sys.exit()
, but Twisted
seems to catch it! How do I exit my program?Use reactor.stop()
instead. This will cleanly shutdown the
reactor.
The .transport
object (which implements the ITransport
interface) offers a pair
of methods named getPeer
and getHost
.
getPeer
will give you a tuple that describes the address of the
system at the other end of the connection. For example:
class MyProtocol(protocol.Protocol): def connectionMade(self): print "connection from", self.transport.getPeer()
No. It is a production grade server. It is running continously on several sites and has been proven quite stable. The server can take loads of up to 3000 users at a time and still keep churning several million requests a day, even on low end hardware. It can serve static files or dynamically rendered pages.
Yes. It works out-of-the-box, so long as you've got the standalone php interpreter installed.
Can it ever!
You can decide to go with one big process for all of them, a front server and a seperate server for each virtual host (for example, for permission reasons), and you can even mix-and-match between Apache and Twisted (for example, put Apache in the front and have Twisted handle some subset of the virtual host).
You probably have code that's survived the upgrade from PyXML's
minidom
to Twisted's microdom
. Try deleting any
.pxp
files that you have lying around and the error will probably
go away.
If you are subclassing Page
, you can add a class attribute addSlash = 0
, like this:
class Foo(page.Page): addSlash = 0
If you are still subclassing Controller
, you can put the addSlash = 0
there. Consider subclassing Page
instead, as having a Model
, View
, Controller
triad as the base of a
Page
will be deprecated
in the near future.
If you're just using the generic Page
instance, you can set it after
creation like this:
resource = page.Page("foo") resource.addSlash = 0
The default behavior of Woven is now to automatically add a slash because it makes creating relative links far easier, ironically ;-)
Use the RawText
view.
Are you using an RPY? Add a single line containing cache()
as
the first line of your RPY.
An RPY file is executed every time it is accessed, so the call to guard.SessionWrapper
is executed
once per request, making a new SessionWrapper for each request. There should be
only one SessionWrapper object for your application. Caching the RPY file
enforces this.
Firstly, the client must send a reference when it connects to the
perspective broker. This can be done by passing the reference as a parameter to
pb.connect
.
At the server end, you must override the Perspective.attach
, which is called when a client attaches
to a perspective. The first argument of this method is a remote reference to
the client object that was passed to pb.connect
.
Note that a single perspective can have many attached clients. For further
information, see Managing Clients of Perspectives
HOWTO and the twisted.spread.pb
API docs.
Great! Read our the docs, and if you're feeling generous, contribute patches.
Use unified diff. Either use svn diff
or, better yet, make a clean checkout and use diff
-urN
between them. Make sure your patch applies cleanly. In
your post to the mailing list, make sure it is inlined and without any
word wrapping.
Add it to the bug tracker, and if it's an urgent or important issue you may want to tell the mailing list. about the issue you added
You have 3 options:
We are doing the best we can, and there is documentation in progress for many parts of Twisted. There is a limit to how much we can do in our free time. See also the answer to the next question.
Now you can, with twisted.lore
. See the manual
page for lore
. For
source format documentation, see the documentation
standard description. For a more comprehensive explanation, see
the Lore HOWTO.
Unless it is a show-stopper bug, we usually won't fix it if it's already fixed in Subversion, so you would do well to look there. Then send any pertinent information about the bug (hopefully as much information needed to reproduce it: OS, Subversion versions of any important files, Python version, code you wrote or things you did to trigger the bug, etc.) to the mailing list. If no one answers immediately, you should add it to the bug tracker.
Ask for help where the Twisted team hangs out
First, note that in many cases this is the wrong thing to do: if
you have a question about a part of Twisted, it's usually better to
e-mail the mailing list. However, the preferred e-mail addresses for
all Twisted developers are listed in the file CREDITS
in the
Subversion repository.