~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to doc/core/howto/faq.html

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-01-16 19:56:10 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060116195610-ykmxbia4mnnod9o2
Tags: 2.1.0-0ubuntu2
debian/copyright: Include copyright for python 2.3; some 2.3 files
are included in the upstream tarball, but not in the binary packages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: The Twisted FAQ</title><link href="../howto/stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">The Twisted FAQ</h1><div class="toc"><ol><li><a href="#auto0">General</a></li><ul><li><a href="#auto1">What is Twisted?</a></li><li><a href="#auto2">Why should I use Twisted?</a></li><li><a href="#auto3">I have a problem getting Twisted.</a></li><li><a href="#auto4">Why is Twisted so big?</a></li><li><a href="#auto5">But won't Twisted bloat my program, since it's so big?</a></li></ul><li><a href="#auto6">Stability</a></li><ul><li><a href="#auto7">Does the 1.0 release mean that all of Twisted's APIs are stable?</a></li><li><a href="#auto8">Which parts of Twisted are stable?</a></li></ul><li><a href="#auto9">Installation</a></li><ul><li><a href="#auto10">I run mktap (from site-packages/twisted/scripts/mktap.py)
3
 
and nothing happens!</a></li><li><a href="#auto11">Why do the Debian packages for Alphas and Release Candidates have weird versions containing old version numbers?</a></li></ul><li><a href="#auto12">Core Twisted</a></li><ul><li><a href="#auto13">How can I access self.factory from my Protocol's __init__?</a></li><li><a href="#auto14">Where can I find out how to write Twisted servers?</a></li><li><a href="#auto15">When I try to install my reactor, I get errors about a reactor
4
 
already being installed. What gives?</a></li><li><a href="#auto16">twistd won't load my .tap file! What's this
5
 
Ephemeral nonsense?</a></li><li><a href="#auto17">I get Interrupted system call errors when I use os.popen2.  How do I read results from a sub-process in
6
 
Twisted?</a></li><li><a href="#auto18">Why don't my spawnProcess programs see my environment variables?</a></li><li><a href="#auto19">My Deferred or DeferredList never fires, so my program just mysteriously
7
 
hangs!  What's wrong?</a></li><li><a href="#auto20">My exceptions and tracebacks aren't getting printed!</a></li><li><a href="#auto21">How do I use Deferreds to make my blocking code non-blocking?</a></li><li><a href="#auto22">I get exceptions.ValueError: signal only works in main thread when I
8
 
try to run my Twisted program!  What's wrong?</a></li><li><a href="#auto23">I'm trying to stop my program with sys.exit(), but Twisted
9
 
seems to catch it!  How do I exit my program?</a></li><li><a href="#auto24">How do I find out the IP address of the other end of my connection?</a></li><li><a href="#auto25">Why don't Twisted's network methods support Unicode objects as well as
10
 
strings?</a></li></ul><li><a href="#auto26">Perspective Broker</a></li><ul><li><a href="#auto27">How can I get the reference to a client from a Perspective?</a></li></ul><li><a href="#auto28">Requests and Contributing</a></li><ul><li><a href="#auto29">Twisted is cool, but I need to add more functionality.</a></li><li><a href="#auto30">I have a patch. How do I maximize the chances the Twisted developers
11
 
will include it?</a></li><li><a href="#auto31">And to whom do I send it?</a></li><li><a href="#auto32">My company would love to use Twisted, but it's missing feature X, can you implement it?</a></li></ul><li><a href="#auto33">Documentation</a></li><ul><li><a href="#auto34">Twisted really needs documentation for X, Y or Z - how come it's not documented?.</a></li><li><a href="#auto35">Wow the Twisted documentation is nice! I want my docs to look like that
12
 
too!</a></li></ul><li><a href="#auto36">Communicating with us</a></li><ul><li><a href="#auto37">There's a bug in Twisted. Where do I report it?</a></li><li><a href="#auto38">Where do I go for help?</a></li><li><a href="#auto39">How do I e-mail a Twisted developer?</a></li></ul></ol></div><div class="content"><span></span><h2>General<a name="auto0"></a></h2><h3>What is <q>Twisted</q>?<a name="auto1"></a></h3><p>Please see
13
 
<a href="http://twistedmatrix.com/products/twisted">Twisted</a></p><h3>Why should I use Twisted?<a name="auto2"></a></h3><p>See <a href="http://twistedmatrix.com/services/twisted-advantage">The
14
 
Twisted Advantage</a></p><h3>I have a problem <q>getting</q> Twisted.<a name="auto3"></a></h3><p>Did you check the HOWTO collection? There are so many documents there
15
 
that they might overwhelm you... try starting from the index, reading through
16
 
the overviews and seeing if there seems to be a chapter which explains what
17
 
you need to. You can try reading the PostScript or PDF formatted books,
18
 
inside the distribution. And, remember, the source will be with
19
 
you... always.</p><h3>Why is Twisted so big?<a name="auto4"></a></h3><p>Twisted is a lot of things, rolled into one big package. We're not sure if 
20
 
it'll stay this way, yet, but for now, if you have only specific needs, we
21
 
recommend grabbing the big Twisted tarball, and if you want, you can run the
22
 
'setup.py' script with a modified config file to generate a package with only
23
 
certain Twisted sub-packages. Twisted as a whole makes it into many operating 
24
 
system distributions (FreeBSD, Debian and Gentoo, at least) so size shouldn't
25
 
be an issue for the end developer or user. In addition, packaging Twisted
26
 
as a whole makes sure the end users do not have to worry about versioning
27
 
parts of Twisted and inter-version compatibility.</p><p>If you are distributing Twisted to end-users, you can base your distribution
28
 
on the <q>Nodocs</q> packages, which are signficantly smaller.</p><h3>But won't Twisted bloat my program, since it's so big?<a name="auto5"></a></h3><p>No. You only need to import the sub-packages which you want to use, meaning
29
 
only those will be loaded into memory. So if you write a low-level network
30
 
protocol, you'd only import twisted.internet, leaving out extraneous things
31
 
like twisted.web, etc. Twisted itself is very careful with internal
32
 
dependancies, so importing one subpackage is not likely to import the whole
33
 
twisted package.</p><h2>Stability<a name="auto6"></a></h2><h3>Does the 1.0 release mean that all of Twisted's APIs are stable?<a name="auto7"></a></h3><p>No, only specific parts of Twisted are stable, i.e. we only promise
34
 
backwards compatibility for some parts of Twisted. While these APIs may be
35
 
extended, they will not change in ways that break existing code that uses
36
 
them. </p><p>While other parts of Twisted are not stable, we will however do
37
 
our best to make sure that there is backwards compatibility for these parts
38
 
as well. In general, the more the module or package are used, and the closer they
39
 
are to being feature complete, the more we will concentrate on providing backwards
40
 
compatibility when API changes take place.</p><h3>Which parts of Twisted are stable?<a name="auto8"></a></h3><p>Only modules explictily marked as such can be considered stable. Semi-stable
41
 
modules may change, but not in a large way and some sort of backwards-compatibily
42
 
will probably be provided. If no comment about API stability is present, assume
43
 
the module is unstable.</p><p>In Twisted 1.1, <em>most of twisted.internet, .cred and
44
 
.application are completely stable</em> (excepting of course code
45
 
marked as deprecated).</p><p>But as always, the only accurate way of knowing a module's stability is reading
46
 
the module's docstrings.</p><h2>Installation<a name="auto9"></a></h2><h3>I run mktap (from site-packages/twisted/scripts/mktap.py)
47
 
and nothing happens!<a name="auto10"></a></h3><p>Don't run scripts out of <code>site-packages</code>.  The Windows
48
 
installer should install executable scripts to someplace like
49
 
<code>C:\Python22\scripts\</code>, *nix installers put them in
50
 
<code>$PREFIX/bin</code>, which should be in your $PATH.</p><h3>Why do the Debian packages for Alphas and Release Candidates have weird versions containing old version numbers?<a name="auto11"></a></h3><p>
51
 
An example: 1.0.6+1.0.7rc1-1
52
 
</p><p>
53
 
 
54
 
In Debian versioning, 1.0.7rc1 is <em>greater than</em> 1.0.7. This
55
 
means that if you install a package with Version: 1.0.7rc1, and then
56
 
that package gets a new version 1.0.7, apt will not upgrade it for
57
 
you, because 1.0.7 looks like an older version. So, we prefix the
58
 
previous version to the actual version. 1.0.6+1.0.7rc1 is <em>less
59
 
than</em> 1.0.7.
60
 
 
61
 
</p><h2>Core Twisted<a name="auto12"></a></h2><h3>How can I access self.factory from my Protocol's __init__?<a name="auto13"></a></h3><p>You can't.  A Protocol doesn't have a Factory when it is created.  Instead,
62
 
you should probably be doing that in your Protocol's
63
 
<code>connectionMade</code> method.</p><p>Similarly you shouldn't be doing <q>real</q> work, like connecting to
64
 
databases, in a Factory's <code>__init__</code> either.  Instead, do that in
65
 
<code>startFactory</code>.</p><p>See <a href="servers.html">Writing Servers</a> and 
66
 
<a href="clients.html">Writing Clients</a> for more details.</p><h3>Where can I find out how to write Twisted servers?<a name="auto14"></a></h3><p>Try <a href="servers.html">Writing Servers</a>.</p><h3>When I try to install my reactor, I get errors about a reactor
67
 
already being installed. What gives?<a name="auto15"></a></h3><p>Here's the rule - installing a reactor should always be the
68
 
<strong>first</strong> thing you do, and I do mean first. Importing other stuff
69
 
before you install the reactor can break your code.</p><p>Tkinter and wxPython support, as they do not install a new reactor, can be
70
 
done at any point, IIRC.</p><h3><code>twistd</code> won't load my <code>.tap</code> file! What's this
71
 
Ephemeral nonsense?<a name="auto16"></a></h3><p>When the pickled application state cannot be loaded for some reason, it
72
 
is common to get a rather opaque error like so:</p><pre class="shell">
73
 
% twistd -f test2.tap 
74
 
 
75
 
Failed to load application: global name 'initRun' is not defined
76
 
</pre><p>The rest of the error will try to explain how to solve this problem,
77
 
but a short comment first: this error is indeed terse -- but there is
78
 
probably more data available elsewhere -- namely, the <code>twistd.log</code>
79
 
file. Open it up to see the full exception.</p><p>The error might also look like this:</p><pre class="shell">
80
 
Failed to load application: &lt;twisted.persisted.styles.Ephemeral instance at 
81
 
0x82450a4&gt; is not safe for unpickling
82
 
</pre><p>To load a <code>.tap</code> file, as with any unpickling operation, all
83
 
the classes used by all the objects inside it must be accessible at the time
84
 
of the reload. This may require the PYTHONPATH variable to have the same
85
 
directories as were available when the application was first pickled.</p><p>A common problem occurs in single-file programs which define a few
86
 
classes, then create instances of those classes for use in a server of some
87
 
sort. If the class is used directly, the name of the class will be recorded
88
 
in the <code>.tap</code> file as something like
89
 
<code>__main__.MyProtocol</code>. When the application is reloaded, it will
90
 
look for the class definition in <code>__main__</code>, which probably won't
91
 
have it. The unpickling routines need to know the module name, and therefore
92
 
the source file, from which the class definition can be loaded.</p><p>The way to fix this is to import the class from the same source file that
93
 
defines it: if your source file is called <code>myprogram.py</code> and
94
 
defines a class called <code>MyProtocol</code>, you will need to do a
95
 
<code>from myprogram import MyProtocol</code> before (and in the same
96
 
namespace as) the code that references the MyProtocol class. This makes it
97
 
important to write the module cleanly: doing an <code>import
98
 
myprogram</code> should only define classes, and should not cause any other
99
 
subroutines to get run. All the code that builds the Application and saves
100
 
it out to a <code>.tap</code> file must be inside an <code>if __name__ ==
101
 
'__main__'</code> clause to make sure it is not run twice (or more).</p><p>When you import the class from the module using an <q>external</q> name,
102
 
that name will be recorded in the pickled <code>.tap</code> file. When the
103
 
<code>.tap</code> is reloaded by <code>twistd</code>, it will look for
104
 
<code>myprogram.py</code> to provide the definition of
105
 
<code>MyProtocol</code>.</p><p>Here is a short example of this technique:</p><pre class="python">
106
 
<span class="py-src-comment"># file dummy.py
107
 
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>
108
 
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Dummy</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">Protocol</span>): <span class="py-src-keyword">pass</span>
109
 
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
110
 
    <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">service</span>, <span class="py-src-variable">internet</span>
111
 
    <span class="py-src-variable">a</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">Application</span>(<span class="py-src-string">&quot;dummy&quot;</span>)
112
 
    <span class="py-src-keyword">import</span> <span class="py-src-variable">dummy</span>
113
 
    <span class="py-src-variable">f</span> = <span class="py-src-variable">protocol</span>.<span class="py-src-variable">Factory</span>()
114
 
    <span class="py-src-variable">f</span>.<span class="py-src-variable">protocol</span> = <span class="py-src-variable">dummy</span>.<span class="py-src-variable">Dummy</span> <span class="py-src-comment"># Note! Not &quot;Dummy&quot;</span>
115
 
    <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">2000</span>, <span class="py-src-variable">f</span>).<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">a</span>)
116
 
    <span class="py-src-variable">a</span>.<span class="py-src-variable">save</span>()
117
 
</pre><h3>I get <q>Interrupted system call</q> errors when I use <code class="python">os.popen2</code>.  How do I read results from a sub-process in
118
 
Twisted?<a name="auto17"></a></h3><p>You should be using <code class="python">reactor.spawnProcess</code> (see
119
 
<code base="twisted.internet" class="API">interfaces.IReactorProcess.spawnProcess</code>).
120
 
There's also a convenience function, <code base="twisted.internet.utils" class="API">getProcessOutput</code>, in <code class="API">twisted.internet.utils</code>.</p><h3>Why don't my spawnProcess programs see my environment variables?<a name="auto18"></a></h3><p><code base="twisted.internet.interfaces.IReactorProcess" class="API">spawnProcess</code>
121
 
defaults to clearing the environment of child processes as a security
122
 
feature. You can either provide a dictionary with exactly the name-value
123
 
pairs you want the child to use, or you can simply pass in
124
 
<code>os.environ</code> to inherit the complete environment. </p><h3>My Deferred or DeferredList never fires, so my program just mysteriously
125
 
hangs!  What's wrong?<a name="auto19"></a></h3><p>It really depends on what your program is doing, but the most common cause
126
 
is this: it <em>is</em> firing -- but it's an error, not a success, and you
127
 
have forgotten to add an <a href="glossary.html#errback">errback</a>, so
128
 
nothing happens.  Always add errbacks!</p><p>The reason this happens is that unhandled errors in Deferreds get printed
129
 
when the Deferred is garbage collected. Make sure your Deferred is garbage
130
 
collected by deleting all references to it when you are done with it, e.g.
131
 
after <code class="python">callback()</code> is called.</p><h3>My exceptions and tracebacks aren't getting printed!<a name="auto20"></a></h3><p>See previous question.</p><h3>How do I use Deferreds to make my blocking code non-blocking?<a name="auto21"></a></h3><a name="deferreds-aren't-magic"></a><p>You don't.  Deferreds don't magically turn a blocking function call into a
132
 
non-blocking one.  A Deferred is just a simple object that represents a
133
 
<em>deferred result</em>, with methods to allow convenient adding of
134
 
callbacks.  (This is a common misunderstanding; suggestions on how to make this
135
 
clearer in the <a href="defer.html">Deferred Execution</a> howto are
136
 
welcome!)</p><p>If you have blocking code that you want to use non-blockingly in Twisted,
137
 
either rewrite it to be non-blocking, or run it in a thread.  There is a
138
 
convenience function, <code base="twisted.internet.threads" class="API">deferToThread</code>, to help you with the
139
 
threaded approach -- but be sure to read <a href="threading.html">Using
140
 
Threads in Twisted</a>.</p><h3>I get <q>exceptions.ValueError: signal only works in main thread</q> when I
141
 
try to run my Twisted program!  What's wrong?<a name="auto22"></a></h3><p>The default reactor, by default, will install signal handlers to catch
142
 
events like Ctrl-C, SIGTERM, and so on.  However, you can't install signal
143
 
handlers from non-main threads in Python, which means that
144
 
<code>reactor.run()</code> will cause an
145
 
error.  Pass the <code>installSignalHandlers=0</code> keyword argument to
146
 
<code>reactor.run</code> (or <code>Application.run</code>) to work around
147
 
this.</p><h3>I'm trying to stop my program with <code>sys.exit()</code>, but Twisted
148
 
seems to catch it!  How do I exit my program?<a name="auto23"></a></h3><p>Use <code>reactor.stop()</code> instead.  This will cleanly shutdown the
149
 
reactor.</p><h3>How do I find out the IP address of the other end of my connection?<a name="auto24"></a></h3><p>The <code>.transport</code> object (which implements the <code base="twisted.internet.interfaces" class="API">ITransport</code> interface) offers a pair
150
 
of methods named <code base="twisted.internet.interfaces.ITransport" class="API">getPeer</code> and <code base="twisted.internet.interfaces.ITransport" class="API">getHost</code>.
151
 
<code>getPeer</code> will give you a tuple that describes the address of the
152
 
system at the other end of the connection. For example:</p><pre class="python">
153
 
<span class="py-src-keyword">class</span> <span class="py-src-identifier">MyProtocol</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">Protocol</span>):
154
 
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
155
 
        <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;connection from&quot;</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">getPeer</span>()
156
 
</pre><h3>Why don't Twisted's network methods support Unicode objects as well as
157
 
strings?<a name="auto25"></a></h3><p>In general, such methods (eg <code base="twisted.internet.abstract" class="API">FileDescriptor</code>'s <code>write</code>)
158
 
are designed to send bytes over the network. These methods use non-Unicode
159
 
string objects as a container for the bytes that they send and receive.</p><p>Unicode objects are not byte-based and are an abstraction used for
160
 
representing strings of human readable text. In order to send Unicode strings
161
 
using these methods, you should explicitly specify a byte-based encoding for
162
 
them, for example: <code>s.encode(&quot;utf-8&quot;)</code> and explicitly decode them
163
 
at the receiving end.</p><p>Twisted cannot choose an encoding for you at this level: your encoding
164
 
choice will be protocol specific and may need to be specified in the message
165
 
you send (for example, HTTP headers include a encoding specification).</p><p>For a more complete discussion of the distinction between Unicode strings
166
 
and specific encodings of Unicode strings, see the following articles:</p><ul><li>Dan Sugalski's <a href="http://www.sidhe.org/~dan/blog/archives/000255.html">What the heck is: A
167
 
string</a>; and</li><li>Joel Spolsky's <a href="http://www.joelonsoftware.com/articles/Unicode.html">The Absolute
168
 
Minimum Every Software Developer Absolutely, Positively Must Know
169
 
About Unicode and Character Sets (No Excuses!)</a>.</li></ul><h2>Perspective Broker<a name="auto26"></a></h2><h3>How can I get the reference to a client from a Perspective?<a name="auto27"></a></h3><p>Firstly, the client must send a reference when it connects to the
170
 
perspective broker. This can be done by passing the reference as a parameter to
171
 
<code base="twisted.spread" class="API">pb.connect</code>.</p><p>At the server end, you must override the <code base="twisted.spread.pb" class="API">Perspective.attach</code>, which is called when a client attaches
172
 
to a perspective. The first argument of this method is a remote reference to
173
 
the client object that was passed to <code base="twisted.spread" class="API">pb.connect</code>. </p><p>Note that a single perspective can have many attached clients. For further
174
 
information, see <a href="pclients.html">Managing Clients of Perspectives</a>
175
 
HOWTO and the <code class="API">twisted.spread.pb</code> API docs.</p><h2>Requests and Contributing<a name="auto28"></a></h2><h3>Twisted is cool, but I need to add more functionality.<a name="auto29"></a></h3><p>Great! Read our the docs, and if you're feeling generous, contribute
176
 
patches.</p><h3>I have a patch. How do I maximize the chances the Twisted developers
177
 
will include it?<a name="auto30"></a></h3><p>Use unified diff. Either use <code class="shell">svn diff</code>
178
 
or, better yet, make a clean checkout and use <code class="shell">diff
179
 
-urN</code> between them. Make sure your patch applies cleanly. In
180
 
your post to the mailing list, make sure it is inlined and without any
181
 
word wrapping.</p><h3>And to whom do I send it?<a name="auto31"></a></h3><p>Add it to the <a href="http://twistedmatrix.com/bugs/">bug tracker</a>, and if it's an urgent or important issue you may want to tell the <a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python">mailing list</a>. about the issue you added</p><h3>My company would love to use Twisted, but it's missing feature X, can you implement it?<a name="auto32"></a></h3><p>You have 3 options:</p><ul><li>Pay one of the Twisted developers to implement the feature.</li><li>Implement the feature yourself.</li><li>Add a feature request to our bug tracker. We will try to implement the
182
 
feature, but there are no guarantees when and if this will happen.</li></ul><h2>Documentation<a name="auto33"></a></h2><h3>Twisted really needs documentation for X, Y or Z - how come it's not documented?.<a name="auto34"></a></h3><p>Twisted's documentation is a work in progress, and one that we would
183
 
appreciate assistance with. If you notice a gap or flaw in the documentation,
184
 
please file a bug in <a href="http://twistedmatrix.com/bugs/">the Twisted bug
185
 
tracker</a> and mark it as having topic 'documentation'. Patches
186
 
appreciated.</p><h3>Wow the Twisted documentation is nice! I want my docs to look like that
187
 
too!<a name="auto35"></a></h3><p>Now you can, with <a href="http://twistedmatrix.com/projects/lore">Lore</a>. </p><h2>Communicating with us<a name="auto36"></a></h2><h3>There's a bug in Twisted. Where do I report it?<a name="auto37"></a></h3><p>Unless it is a show-stopper bug, we usually won't fix it if it's already
188
 
fixed in <a href="http://twistedmatrix.com/developers/cvs">Subversion</a>, so
189
 
check if it is fixed there. If it is not fixed in Subversion, you should add
190
 
it to the <a href="http://twistedmatrix.com/bugs/">bug tracker</a>, including
191
 
pertinent information about the bug (hopefully as much information needed to
192
 
reproduce it: OS, Subversion versions of any important files, Python version,
193
 
code you wrote or things you did to trigger the bug, etc. If the bug appears
194
 
to be severe, you should also raise it on the <a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python">mailing
195
 
list</a>, with a pointer to the issue already filed in the bug tracker.</p><h3>Where do I go for help?<a name="auto38"></a></h3><p>Ask for help <a href="http://twistedmatrix.com/services/online-help">where
196
 
the Twisted team hangs out</a></p><h3>How do I e-mail a Twisted developer?<a name="auto39"></a></h3><p>First, note that in many cases this is the wrong thing to do: if
197
 
you have a question about a part of Twisted, it's usually better to
198
 
e-mail the mailing list. However, the preferred e-mail addresses for
199
 
all Twisted developers are listed in the file <q>CREDITS</q> in the
200
 
Subversion repository.</p></div><p><a href="../howto/index.html">Index</a></p><span class="version">Version: 2.0.1</span></body></html>
 
 
b'\\ No newline at end of file'