1 | n/a | # |
---|
2 | n/a | # Example where a pool of http servers share a single listening socket |
---|
3 | n/a | # |
---|
4 | n/a | # On Windows this module depends on the ability to pickle a socket |
---|
5 | n/a | # object so that the worker processes can inherit a copy of the server |
---|
6 | n/a | # object. (We import `multiprocessing.reduction` to enable this pickling.) |
---|
7 | n/a | # |
---|
8 | n/a | # Not sure if we should synchronize access to `socket.accept()` method by |
---|
9 | n/a | # using a process-shared lock -- does not seem to be necessary. |
---|
10 | n/a | # |
---|
11 | n/a | # Copyright (c) 2006-2008, R Oudkerk |
---|
12 | n/a | # All rights reserved. |
---|
13 | n/a | # |
---|
14 | n/a | |
---|
15 | n/a | import os |
---|
16 | n/a | import sys |
---|
17 | n/a | |
---|
18 | n/a | from multiprocessing import Process, current_process, freeze_support |
---|
19 | n/a | from http.server import HTTPServer |
---|
20 | n/a | from http.server import SimpleHTTPRequestHandler |
---|
21 | n/a | |
---|
22 | n/a | if sys.platform == 'win32': |
---|
23 | n/a | import multiprocessing.reduction # make sockets pickable/inheritable |
---|
24 | n/a | |
---|
25 | n/a | |
---|
26 | n/a | def note(format, *args): |
---|
27 | n/a | sys.stderr.write('[%s]\t%s\n' % (current_process().name, format % args)) |
---|
28 | n/a | |
---|
29 | n/a | |
---|
30 | n/a | class RequestHandler(SimpleHTTPRequestHandler): |
---|
31 | n/a | # we override log_message() to show which process is handling the request |
---|
32 | n/a | def log_message(self, format, *args): |
---|
33 | n/a | note(format, *args) |
---|
34 | n/a | |
---|
35 | n/a | def serve_forever(server): |
---|
36 | n/a | note('starting server') |
---|
37 | n/a | try: |
---|
38 | n/a | server.serve_forever() |
---|
39 | n/a | except KeyboardInterrupt: |
---|
40 | n/a | pass |
---|
41 | n/a | |
---|
42 | n/a | |
---|
43 | n/a | def runpool(address, number_of_processes): |
---|
44 | n/a | # create a single server object -- children will each inherit a copy |
---|
45 | n/a | server = HTTPServer(address, RequestHandler) |
---|
46 | n/a | |
---|
47 | n/a | # create child processes to act as workers |
---|
48 | n/a | for i in range(number_of_processes - 1): |
---|
49 | n/a | Process(target=serve_forever, args=(server,)).start() |
---|
50 | n/a | |
---|
51 | n/a | # main process also acts as a worker |
---|
52 | n/a | serve_forever(server) |
---|
53 | n/a | |
---|
54 | n/a | |
---|
55 | n/a | def test(): |
---|
56 | n/a | DIR = os.path.join(os.path.dirname(__file__), '..') |
---|
57 | n/a | ADDRESS = ('localhost', 8000) |
---|
58 | n/a | NUMBER_OF_PROCESSES = 4 |
---|
59 | n/a | |
---|
60 | n/a | print('Serving at http://%s:%d using %d worker processes' % \ |
---|
61 | n/a | (ADDRESS[0], ADDRESS[1], NUMBER_OF_PROCESSES)) |
---|
62 | n/a | print('To exit press Ctrl-' + ['C', 'Break'][sys.platform=='win32']) |
---|
63 | n/a | |
---|
64 | n/a | os.chdir(DIR) |
---|
65 | n/a | runpool(ADDRESS, NUMBER_OF_PROCESSES) |
---|
66 | n/a | |
---|
67 | n/a | |
---|
68 | n/a | if __name__ == '__main__': |
---|
69 | n/a | freeze_support() |
---|
70 | n/a | test() |
---|