Exiting a program from within an object method.

Steve Holden sholden at holdenweb.com
Thu Jan 4 13:19:13 EST 2001


Benjamin Scherrey <scherrey at innoverse.com> wrote in message
news:9325ne014j at news2.newsguy.com...
>         I've written a small python program that instantiates an object
which
> inherits from SocketServer.BaseRequestHandler. The __main__ function
starts
> this thing up with the serve_forever() method. Inside the handle() method
> of my object I check for a command to shutdown and, if received, call
> sys.exit(0). All this does is generate a SystemExit exception and does not
> terminate my program. Even if I wrap the call to serve_forever() with a
> try: except: block, the exception is not caught. I presume because the
> object's handle() method is possibly being executed in a child thread and
> python must not support cross thread exception handling (I'm not
> instantiating any threads explicitly, I'm assuming that the
> BaseRequestHandler is doing this internally)?
>
The SocketServer libraries do not perform forking, or use threads, unless
you ask them to.  You do this by building classes which inherit from
ForkingXXServer or ThreadingXXXServer respectively, where XXX will either be
TCP or UDP (or Unix on U**x systems only).

>         What's a simple way to have my object exit the application
cleanly?
>
The serve_forever() method simply makes repeated requests to the
handle_request() method, which gets a request (by default using
socket.accept())  and calls process_request().  This (unless overriden)
calls finish_request(), which finally (unless overridden) creates an
instance of the RequestHandlerClass which you provided when you created your
server.  This instantiation gets three arguments: the request, the client
address, and the server object itself.

The documentation states: "If the user-provided handle() method of the
handler class raises an exception, the server's handle_error() method will
be called."  So the behavior you are seeing is to be expected.

One simple solution is to override the handle_error() method, and detect the
SystemExit.  If that's what caused the problem you can simply re-raise it to
terminate your server process.

Below is a simple program which shows you a framework for this.  A telnet to
port 8888 on the local host does now indeed terminate the server as
required.

regards
 Steve

import sys, SocketServer

class ExitRequester(SocketServer.BaseRequestHandler):

    def handle(self):
        print "About to exit"
        sys.exit(0)

class MyServer(SocketServer.TCPServer):

    def handle_error(self, request, client_address):
        """Handle an error gracefully.  Overrides standard method.

        The default is to print a traceback and continue, except in
        the case of a SystemExit exception, which should terminate
        processing.

        """
        import exceptions
        etype, evalue = sys.exc_info()[:2]
        if etype is exceptions.SystemExit: raise
        print '-'*40
        print 'Exception happened during processing of request from',
        print client_address
        import traceback
        traceback.print_exc(1000, sys.stdout)
        print '-'*40
        sys.stdout.flush()

s = MyServer(('127.0.0.1', 8888), ExitRequester)

s.serve_forever()







More information about the Python-list mailing list