Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(16)

Side by Side Diff: Doc/library/socketserver.rst

Issue 26404: socketserver context manager
Patch Set: Created 4 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 :mod:`socketserver` --- A framework for network servers 1 :mod:`socketserver` --- A framework for network servers
2 ======================================================= 2 =======================================================
3 3
4 .. module:: socketserver 4 .. module:: socketserver
5 :synopsis: A framework for network servers. 5 :synopsis: A framework for network servers.
6 6
7 **Source code:** :source:`Lib/socketserver.py` 7 **Source code:** :source:`Lib/socketserver.py`
8 8
9 -------------- 9 --------------
10 10
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 or because it returns a lot of data which the client is slow to process. The 45 or because it returns a lot of data which the client is slow to process. The
46 solution is to create a separate process or thread to handle each request; the 46 solution is to create a separate process or thread to handle each request; the
47 :class:`ForkingMixIn` and :class:`ThreadingMixIn` mix-in classes can be used to 47 :class:`ForkingMixIn` and :class:`ThreadingMixIn` mix-in classes can be used to
48 support asynchronous behaviour. 48 support asynchronous behaviour.
49 49
50 Creating a server requires several steps. First, you must create a request 50 Creating a server requires several steps. First, you must create a request
51 handler class by subclassing the :class:`BaseRequestHandler` class and 51 handler class by subclassing the :class:`BaseRequestHandler` class and
52 overriding its :meth:`~BaseRequestHandler.handle` method; 52 overriding its :meth:`~BaseRequestHandler.handle` method;
53 this method will process incoming 53 this method will process incoming
54 requests. Second, you must instantiate one of the server classes, passing it 54 requests. Second, you must instantiate one of the server classes, passing it
55 the server's address and the request handler class. Then call the 55 the server's address and the request handler class. It is recommended to initiat e
56 the class using :keyword:`with` statement. Then call the
Martin Panter 2016/02/24 02:55:12 “Initiate” seems strange to me; also there is a mi
palaviv 2016/02/24 10:05:34 Done.
56 :meth:`~BaseServer.handle_request` or 57 :meth:`~BaseServer.handle_request` or
57 :meth:`~BaseServer.serve_forever` method of the server object to 58 :meth:`~BaseServer.serve_forever` method of the server object to
58 process one or many requests. Finally, call :meth:`~BaseServer.server_close` 59 process one or many requests. Finally, call :meth:`~BaseServer.server_close`
59 to close the socket. 60 to close the socket (Unless you used the :keyword:`with` statement).
Martin Panter 2016/02/24 02:55:12 Needs a lowercase U (or a full stop somewhere). Bu
palaviv 2016/02/24 10:05:34 I think we should still have the sentence about se
60 61
61 When inheriting from :class:`ThreadingMixIn` for threaded connection behavior, 62 When inheriting from :class:`ThreadingMixIn` for threaded connection behavior,
62 you should explicitly declare how you want your threads to behave on an abrupt 63 you should explicitly declare how you want your threads to behave on an abrupt
63 shutdown. The :class:`ThreadingMixIn` class defines an attribute 64 shutdown. The :class:`ThreadingMixIn` class defines an attribute
64 *daemon_threads*, which indicates whether or not the server should wait for 65 *daemon_threads*, which indicates whether or not the server should wait for
65 thread termination. You should set the flag explicitly if you would like 66 thread termination. You should set the flag explicitly if you would like
66 threads to behave autonomously; the default is :const:`False`, meaning that 67 threads to behave autonomously; the default is :const:`False`, meaning that
67 Python will not exit until all threads created by :class:`ThreadingMixIn` have 68 Python will not exit until all threads created by :class:`ThreadingMixIn` have
68 exited. 69 exited.
69 70
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 Called by the server's constructor to bind the socket to the desired addre ss. 345 Called by the server's constructor to bind the socket to the desired addre ss.
345 May be overridden. 346 May be overridden.
346 347
347 348
348 .. method:: verify_request(request, client_address) 349 .. method:: verify_request(request, client_address)
349 350
350 Must return a Boolean value; if the value is :const:`True`, the request wi ll 351 Must return a Boolean value; if the value is :const:`True`, the request wi ll
351 be processed, and if it's :const:`False`, the request will be denied. Thi s 352 be processed, and if it's :const:`False`, the request will be denied. Thi s
352 function can be overridden to implement access controls for a server. The 353 function can be overridden to implement access controls for a server. The
353 default implementation always returns :const:`True`. 354 default implementation always returns :const:`True`.
355
356
357 .. versionadded:: 3.6
358 Support for the :term:`context manager` protocol was added. Exiting the
359 context manager is equivalent to calling :meth:`server_close`.
354 360
355 361
356 Request Handler Objects 362 Request Handler Objects
357 ----------------------- 363 -----------------------
358 364
359 .. class:: BaseRequestHandler 365 .. class:: BaseRequestHandler
360 366
361 This is the superclass of all request handler objects. It defines 367 This is the superclass of all request handler objects. It defines
362 the interface, given below. A concrete request handler subclass must 368 the interface, given below. A concrete request handler subclass must
363 define a new :meth:`handle` method, and can override any of 369 define a new :meth:`handle` method, and can override any of
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 self.data = self.request.recv(1024).strip() 432 self.data = self.request.recv(1024).strip()
427 print("{} wrote:".format(self.client_address[0])) 433 print("{} wrote:".format(self.client_address[0]))
428 print(self.data) 434 print(self.data)
429 # just send back the same data, but upper-cased 435 # just send back the same data, but upper-cased
430 self.request.sendall(self.data.upper()) 436 self.request.sendall(self.data.upper())
431 437
432 if __name__ == "__main__": 438 if __name__ == "__main__":
433 HOST, PORT = "localhost", 9999 439 HOST, PORT = "localhost", 9999
434 440
435 # Create the server, binding to localhost on port 9999 441 # Create the server, binding to localhost on port 9999
436 server = socketserver.TCPServer((HOST, PORT), MyTCPHandler) 442 with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
437 443 # Activate the server; this will keep running until you
438 # Activate the server; this will keep running until you 444 # interrupt the program with Ctrl-C
439 # interrupt the program with Ctrl-C 445 server.serve_forever()
440 server.serve_forever()
441 446
442 An alternative request handler class that makes use of streams (file-like 447 An alternative request handler class that makes use of streams (file-like
443 objects that simplify communication by providing the standard file interface):: 448 objects that simplify communication by providing the standard file interface)::
444 449
445 class MyTCPHandler(socketserver.StreamRequestHandler): 450 class MyTCPHandler(socketserver.StreamRequestHandler):
446 451
447 def handle(self): 452 def handle(self):
448 # self.rfile is a file-like object created by the handler; 453 # self.rfile is a file-like object created by the handler;
449 # we can now use e.g. readline() instead of raw recv() calls 454 # we can now use e.g. readline() instead of raw recv() calls
450 self.data = self.rfile.readline().strip() 455 self.data = self.rfile.readline().strip()
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 527
523 def handle(self): 528 def handle(self):
524 data = self.request[0].strip() 529 data = self.request[0].strip()
525 socket = self.request[1] 530 socket = self.request[1]
526 print("{} wrote:".format(self.client_address[0])) 531 print("{} wrote:".format(self.client_address[0]))
527 print(data) 532 print(data)
528 socket.sendto(data.upper(), self.client_address) 533 socket.sendto(data.upper(), self.client_address)
529 534
530 if __name__ == "__main__": 535 if __name__ == "__main__":
531 HOST, PORT = "localhost", 9999 536 HOST, PORT = "localhost", 9999
532 server = socketserver.UDPServer((HOST, PORT), MyUDPHandler) 537 with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
533 server.serve_forever() 538 server.serve_forever()
534 539
535 This is the client side:: 540 This is the client side::
536 541
537 import socket 542 import socket
538 import sys 543 import sys
539 544
540 HOST, PORT = "localhost", 9999 545 HOST, PORT = "localhost", 9999
541 data = " ".join(sys.argv[1:]) 546 data = " ".join(sys.argv[1:])
542 547
543 # SOCK_DGRAM is the socket type to use for UDP sockets 548 # SOCK_DGRAM is the socket type to use for UDP sockets
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 sock.sendall(bytes(message, 'ascii')) 589 sock.sendall(bytes(message, 'ascii'))
585 response = str(sock.recv(1024), 'ascii') 590 response = str(sock.recv(1024), 'ascii')
586 print("Received: {}".format(response)) 591 print("Received: {}".format(response))
587 finally: 592 finally:
588 sock.close() 593 sock.close()
589 594
590 if __name__ == "__main__": 595 if __name__ == "__main__":
591 # Port 0 means to select an arbitrary unused port 596 # Port 0 means to select an arbitrary unused port
592 HOST, PORT = "localhost", 0 597 HOST, PORT = "localhost", 0
593 598
594 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) 599 with ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) as server :
595 ip, port = server.server_address 600 ip, port = server.server_address
596 601
597 # Start a thread with the server -- that thread will then start one 602 # Start a thread with the server -- that thread will then start one
598 # more thread for each request 603 # more thread for each request
599 server_thread = threading.Thread(target=server.serve_forever) 604 server_thread = threading.Thread(target=server.serve_forever)
600 # Exit the server thread when the main thread terminates 605 # Exit the server thread when the main thread terminates
601 server_thread.daemon = True 606 server_thread.daemon = True
602 server_thread.start() 607 server_thread.start()
603 print("Server loop running in thread:", server_thread.name) 608 print("Server loop running in thread:", server_thread.name)
604 609
605 client(ip, port, "Hello World 1") 610 client(ip, port, "Hello World 1")
606 client(ip, port, "Hello World 2") 611 client(ip, port, "Hello World 2")
607 client(ip, port, "Hello World 3") 612 client(ip, port, "Hello World 3")
608 613
609 server.shutdown() 614 server.shutdown()
610 server.server_close()
611 615
612 616
613 The output of the example should look something like this:: 617 The output of the example should look something like this::
614 618
615 $ python ThreadedTCPServer.py 619 $ python ThreadedTCPServer.py
616 Server loop running in thread: Thread-1 620 Server loop running in thread: Thread-1
617 Received: Thread-2: Hello World 1 621 Received: Thread-2: Hello World 1
618 Received: Thread-3: Hello World 2 622 Received: Thread-3: Hello World 2
619 Received: Thread-4: Hello World 3 623 Received: Thread-4: Hello World 3
620 624
621 625
622 The :class:`ForkingMixIn` class is used in the same way, except that the server 626 The :class:`ForkingMixIn` class is used in the same way, except that the server
623 will spawn a new process for each request. 627 will spawn a new process for each request.
OLDNEW

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+