@@ -19,28 +19,40 @@ A Mock Web Server
19
19
20
20
This is a very simple web server. (See below for the code.)
21
21
Its only purpose is to wait for a given amount of time.
22
- Test it by running it from the command line::
22
+ Test it by running it from the command line:
23
+
24
+ .. sourcecode :: console
23
25
24
26
$ python simple_server.py
25
27
26
- It will answer like this::
28
+ It will answer like this:
29
+
30
+ .. sourcecode :: console
27
31
28
32
Serving from port 8000 ...
29
33
30
- Now, open a browser and go to this URL::
34
+ Now, open a browser and go to this URL:
35
+
36
+ .. sourcecode :: console
31
37
32
38
http://localhost:8000/
33
39
34
- You should see this text in your browser::
40
+ You should see this text in your browser:
41
+
42
+ .. sourcecode :: console
35
43
36
44
Waited for 0.00 seconds.
37
45
38
- Now, add ``2.5 `` to the URL::
46
+ Now, add ``2.5 `` to the URL:
47
+
48
+ .. sourcecode :: console
39
49
40
50
http://localhost:8000/2.5
41
51
42
52
After pressing enter, it will take 2.5 seconds until you see this
43
- response::
53
+ response:
54
+
55
+ .. sourcecode :: console
44
56
45
57
Waited for 2.50 seconds.
46
58
@@ -49,7 +61,6 @@ Use different numbers and see how long it takes until the server responds.
49
61
The full implementation looks like this:
50
62
51
63
.. literalinclude :: examples/simple_server.py
52
- :language: python
53
64
54
65
Let's have a look into the details.
55
66
This provides a simple multi-threaded web server:
@@ -113,11 +124,15 @@ The function ``time.perf_counter()`` provides a time stamp.
113
124
Taking two time stamps a different points in time and calculating their
114
125
difference provides the elapsed run time.
115
126
116
- Finally, we can run our client::
127
+ Finally, we can run our client:
128
+
129
+ .. sourcecode :: console
117
130
118
131
$ python synchronous_client.py
119
132
120
- and get this output::
133
+ and get this output:
134
+
135
+ .. sourcecode :: console
121
136
122
137
It took 11.08 seconds for a total waiting time of 11.00.
123
138
Waited for 1.00 seconds.
@@ -174,9 +189,7 @@ Therefore, we need to convert our strings in to bytestrings.
174
189
Next, we read header and message from the reader, which is a ``StreamReader ``
175
190
instance.
176
191
We need to iterate over the reader by using a special or loop for
177
- ``asyncio ``:
178
-
179
- .. code-block :: python
192
+ ``asyncio ``::
180
193
181
194
async for raw_line in reader:
182
195
@@ -204,14 +217,15 @@ The interesting things happen in a few lines in ``get_multiple_pages()``
204
217
(the rest of this function just measures the run time and displays it):
205
218
206
219
.. literalinclude :: examples/async_client_blocking.py
207
- :language: python
208
220
:start-after: pages = []
209
221
:end-before: duration
210
222
211
223
We await ``get_page() `` for each page in a loop.
212
224
This means, we wait until each pages has been retrieved before asking for
213
225
the next.
214
- Let's run it from the command-line to see what happens::
226
+ Let's run it from the command-line to see what happens:
227
+
228
+ .. sourcecode :: console
215
229
216
230
$ async_client_blocking.py
217
231
It took 11.06 seconds for a total waiting time of 11.00.
@@ -249,28 +263,26 @@ The interesting part is in this loop:
249
263
We append all return values of ``get_page() `` to our lits of tasks.
250
264
This allows us to send out all request, in our case four, without
251
265
waiting for the answers.
252
- After sending all of them, we wait for the answers, using:
266
+ After sending all of them, we wait for the answers, using::
253
267
254
268
await asyncio.gather(*tasks)
255
269
256
270
The difference here is the use of ``asyncio.gather() `` that is called with all
257
271
our tasks in the list ``tasks `` as arguments.
258
- The ``asyncio.gather(*tasks) `` means for our example with four list entries:
259
-
260
- .. code-block :: python
272
+ The ``asyncio.gather(*tasks) `` means for our example with four list entries::
261
273
262
274
asyncio.gather(tasks[0], tasks[1], tasks[2], tasks[3])
263
275
264
- So, for a list with 100 tasks it would mean:
265
-
266
- .. code-block :: python
276
+ So, for a list with 100 tasks it would mean::
267
277
268
278
asyncio.gather(tasks[0], tasks[1], tasks[2],
269
279
# 96 more tasks here
270
280
tasks[99])
271
281
272
282
273
- Let's see if we got any faster::
283
+ Let's see if we got any faster:
284
+
285
+ .. sourcecode :: console
274
286
275
287
$ async_client_nonblocking.py
276
288
It took 5.08 seconds for a total waiting time of 11.00.
@@ -309,10 +321,11 @@ High-Level Approach with ``aiohttp``
309
321
310
322
The library aiohttp _ allows to write HTTP client and server applications,
311
323
using a high-level approach.
312
- Install with::
324
+ Install with:
313
325
314
- $ pip install aiohttp
326
+ .. sourcecode :: console
315
327
328
+ $ pip install aiohttp
316
329
317
330
.. _aiohttp : https://aiohttp.readthedocs.io/en/stable/
318
331
@@ -352,7 +365,9 @@ with ``asyncio``.
352
365
The only difference is the opened client session and handing over this session
353
366
to ``fetch_page() `` as the first argument.
354
367
355
- Finally, we run this program::
368
+ Finally, we run this program:
369
+
370
+ .. sourcecode :: console
356
371
357
372
$ python aiohttp_client.py
358
373
It took 5.04 seconds for a total waiting time of 11.00.
0 commit comments