~dkuhlman/python-training-materials/Materials

« back to all changes in this revision

Viewing changes to python-2.7.12-docs-html/_sources/library/asynchat.txt

  • Committer: Dave Kuhlman
  • Date: 2017-04-15 16:24:56 UTC
  • Revision ID: dkuhlman@davekuhlman.org-20170415162456-iav9vozzg4iwqwv3
Updated docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
:mod:`asynchat` --- Asynchronous socket command/response handler
 
2
================================================================
 
3
 
 
4
.. module:: asynchat
 
5
   :synopsis: Support for asynchronous command/response protocols.
 
6
.. moduleauthor:: Sam Rushing <rushing@nightmare.com>
 
7
.. sectionauthor:: Steve Holden <sholden@holdenweb.com>
 
8
 
 
9
**Source code:** :source:`Lib/asynchat.py`
 
10
 
 
11
--------------
 
12
 
 
13
This module builds on the :mod:`asyncore` infrastructure, simplifying
 
14
asynchronous clients and servers and making it easier to handle protocols
 
15
whose elements are terminated by arbitrary strings, or are of variable length.
 
16
:mod:`asynchat` defines the abstract class :class:`async_chat` that you
 
17
subclass, providing implementations of the :meth:`collect_incoming_data` and
 
18
:meth:`found_terminator` methods. It uses the same asynchronous loop as
 
19
:mod:`asyncore`, and the two types of channel, :class:`asyncore.dispatcher`
 
20
and :class:`asynchat.async_chat`, can freely be mixed in the channel map.
 
21
Typically an :class:`asyncore.dispatcher` server channel generates new
 
22
:class:`asynchat.async_chat` channel objects as it receives incoming
 
23
connection requests.
 
24
 
 
25
 
 
26
.. class:: async_chat()
 
27
 
 
28
   This class is an abstract subclass of :class:`asyncore.dispatcher`. To make
 
29
   practical use of the code you must subclass :class:`async_chat`, providing
 
30
   meaningful :meth:`collect_incoming_data` and :meth:`found_terminator`
 
31
   methods.
 
32
   The :class:`asyncore.dispatcher` methods can be used, although not all make
 
33
   sense in a message/response context.
 
34
 
 
35
   Like :class:`asyncore.dispatcher`, :class:`async_chat` defines a set of
 
36
   events that are generated by an analysis of socket conditions after a
 
37
   :c:func:`select` call. Once the polling loop has been started the
 
38
   :class:`async_chat` object's methods are called by the event-processing
 
39
   framework with no action on the part of the programmer.
 
40
 
 
41
   Two class attributes can be modified, to improve performance, or possibly
 
42
   even to conserve memory.
 
43
 
 
44
 
 
45
   .. data:: ac_in_buffer_size
 
46
 
 
47
      The asynchronous input buffer size (default ``4096``).
 
48
 
 
49
 
 
50
   .. data:: ac_out_buffer_size
 
51
 
 
52
      The asynchronous output buffer size (default ``4096``).
 
53
 
 
54
   Unlike :class:`asyncore.dispatcher`, :class:`async_chat` allows you to
 
55
   define a first-in-first-out queue (fifo) of *producers*. A producer need
 
56
   have only one method, :meth:`more`, which should return data to be
 
57
   transmitted on the channel.
 
58
   The producer indicates exhaustion (*i.e.* that it contains no more data) by
 
59
   having its :meth:`more` method return the empty string. At this point the
 
60
   :class:`async_chat` object removes the producer from the fifo and starts
 
61
   using the next producer, if any. When the producer fifo is empty the
 
62
   :meth:`handle_write` method does nothing. You use the channel object's
 
63
   :meth:`set_terminator` method to describe how to recognize the end of, or
 
64
   an important breakpoint in, an incoming transmission from the remote
 
65
   endpoint.
 
66
 
 
67
   To build a functioning :class:`async_chat` subclass your  input methods
 
68
   :meth:`collect_incoming_data` and :meth:`found_terminator` must handle the
 
69
   data that the channel receives asynchronously. The methods are described
 
70
   below.
 
71
 
 
72
 
 
73
.. method:: async_chat.close_when_done()
 
74
 
 
75
   Pushes a ``None`` on to the producer fifo. When this producer is popped off
 
76
   the fifo it causes the channel to be closed.
 
77
 
 
78
 
 
79
.. method:: async_chat.collect_incoming_data(data)
 
80
 
 
81
   Called with *data* holding an arbitrary amount of received data.  The
 
82
   default method, which must be overridden, raises a
 
83
   :exc:`NotImplementedError` exception.
 
84
 
 
85
 
 
86
.. method:: async_chat.discard_buffers()
 
87
 
 
88
   In emergencies this method will discard any data held in the input and/or
 
89
   output buffers and the producer fifo.
 
90
 
 
91
 
 
92
.. method:: async_chat.found_terminator()
 
93
 
 
94
   Called when the incoming data stream  matches the termination condition set
 
95
   by :meth:`set_terminator`. The default method, which must be overridden,
 
96
   raises a :exc:`NotImplementedError` exception. The buffered input data
 
97
   should be available via an instance attribute.
 
98
 
 
99
 
 
100
.. method:: async_chat.get_terminator()
 
101
 
 
102
   Returns the current terminator for the channel.
 
103
 
 
104
 
 
105
.. method:: async_chat.push(data)
 
106
 
 
107
   Pushes data on to the channel's fifo to ensure its transmission.
 
108
   This is all you need to do to have the channel write the data out to the
 
109
   network, although it is possible to use your own producers in more complex
 
110
   schemes to implement encryption and chunking, for example.
 
111
 
 
112
 
 
113
.. method:: async_chat.push_with_producer(producer)
 
114
 
 
115
   Takes a producer object and adds it to the producer fifo associated with
 
116
   the channel.  When all currently-pushed producers have been exhausted the
 
117
   channel will consume this producer's data by calling its :meth:`more`
 
118
   method and send the data to the remote endpoint.
 
119
 
 
120
 
 
121
.. method:: async_chat.set_terminator(term)
 
122
 
 
123
   Sets the terminating condition to be recognized on the channel.  ``term``
 
124
   may be any of three types of value, corresponding to three different ways
 
125
   to handle incoming protocol data.
 
126
 
 
127
   +-----------+---------------------------------------------+
 
128
   | term      | Description                                 |
 
129
   +===========+=============================================+
 
130
   | *string*  | Will call :meth:`found_terminator` when the |
 
131
   |           | string is found in the input stream         |
 
132
   +-----------+---------------------------------------------+
 
133
   | *integer* | Will call :meth:`found_terminator` when the |
 
134
   |           | indicated number of characters have been    |
 
135
   |           | received                                    |
 
136
   +-----------+---------------------------------------------+
 
137
   | ``None``  | The channel continues to collect data       |
 
138
   |           | forever                                     |
 
139
   +-----------+---------------------------------------------+
 
140
 
 
141
   Note that any data following the terminator will be available for reading
 
142
   by the channel after :meth:`found_terminator` is called.
 
143
 
 
144
 
 
145
asynchat - Auxiliary Classes
 
146
------------------------------------------
 
147
 
 
148
.. class:: fifo([list=None])
 
149
 
 
150
   A :class:`fifo` holding data which has been pushed by the application but
 
151
   not yet popped for writing to the channel.  A :class:`fifo` is a list used
 
152
   to hold data and/or producers until they are required.  If the *list*
 
153
   argument is provided then it should contain producers or data items to be
 
154
   written to the channel.
 
155
 
 
156
 
 
157
   .. method:: is_empty()
 
158
 
 
159
      Returns ``True`` if and only if the fifo is empty.
 
160
 
 
161
 
 
162
   .. method:: first()
 
163
 
 
164
      Returns the least-recently :meth:`push`\ ed item from the fifo.
 
165
 
 
166
 
 
167
   .. method:: push(data)
 
168
 
 
169
      Adds the given data (which may be a string or a producer object) to the
 
170
      producer fifo.
 
171
 
 
172
 
 
173
   .. method:: pop()
 
174
 
 
175
      If the fifo is not empty, returns ``True, first()``, deleting the popped
 
176
      item.  Returns ``False, None`` for an empty fifo.
 
177
 
 
178
 
 
179
.. _asynchat-example:
 
180
 
 
181
asynchat Example
 
182
----------------
 
183
 
 
184
The following partial example shows how HTTP requests can be read with
 
185
:class:`async_chat`.  A web server might create an
 
186
:class:`http_request_handler` object for each incoming client connection.
 
187
Notice that initially the channel terminator is set to match the blank line at
 
188
the end of the HTTP headers, and a flag indicates that the headers are being
 
189
read.
 
190
 
 
191
Once the headers have been read, if the request is of type POST (indicating
 
192
that further data are present in the input stream) then the
 
193
``Content-Length:`` header is used to set a numeric terminator to read the
 
194
right amount of data from the channel.
 
195
 
 
196
The :meth:`handle_request` method is called once all relevant input has been
 
197
marshalled, after setting the channel terminator to ``None`` to ensure that
 
198
any extraneous data sent by the web client are ignored. ::
 
199
 
 
200
   class http_request_handler(asynchat.async_chat):
 
201
 
 
202
       def __init__(self, sock, addr, sessions, log):
 
203
           asynchat.async_chat.__init__(self, sock=sock)
 
204
           self.addr = addr
 
205
           self.sessions = sessions
 
206
           self.ibuffer = []
 
207
           self.obuffer = ""
 
208
           self.set_terminator("\r\n\r\n")
 
209
           self.reading_headers = True
 
210
           self.handling = False
 
211
           self.cgi_data = None
 
212
           self.log = log
 
213
 
 
214
       def collect_incoming_data(self, data):
 
215
           """Buffer the data"""
 
216
           self.ibuffer.append(data)
 
217
 
 
218
       def found_terminator(self):
 
219
           if self.reading_headers:
 
220
               self.reading_headers = False
 
221
               self.parse_headers("".join(self.ibuffer))
 
222
               self.ibuffer = []
 
223
               if self.op.upper() == "POST":
 
224
                   clen = self.headers.getheader("content-length")
 
225
                   self.set_terminator(int(clen))
 
226
               else:
 
227
                   self.handling = True
 
228
                   self.set_terminator(None)
 
229
                   self.handle_request()
 
230
           elif not self.handling:
 
231
               self.set_terminator(None)  # browsers sometimes over-send
 
232
               self.cgi_data = parse(self.headers, "".join(self.ibuffer))
 
233
               self.handling = True
 
234
               self.ibuffer = []
 
235
               self.handle_request()