Python "instance has no attribute" error when extending SocketServer.TCPServer

StackOverflow https://stackoverflow.com/questions/21863391

  •  13-10-2022
  •  | 
  •  

سؤال

I am trying to overwrite the serve_forever method of the SocketServer.TCPServer class. However i am getting a AttributeError: MyServer instance has no attribute '_MyServer__is_shut_down' error.

__is_shut_down is implemented in the SocketServer.BaseServer class and should be initialised through __init__() of SocketServer.TCPServer . What am i missing?

import SocketServer

class MyServer(SocketServer.TCPServer):

    def __init__(self, server_address, RequestHandlerClass):
            SocketServer.TCPServer.__init__(self, server_address, 
                                             RequestHandlerClass)

    def serve_forever(self, poll_interval=0.5):
        self.__is_shut_down.clear()
        try:
            while not self.__shutdown_request:
                 print "SOMETHING"
                 r, w, e = _eintr_retry(select.select, [self], [], [],
                                       poll_interval)
                 if self in r:
                   self._handle_request_noblock()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()
هل كانت مفيدة؟

المحلول 2

Double underscored values are name mangled in the scope they are declared or referenced in. You need to reference self._BaseServer__is_shut_down (and self._BaseServer__shutdown_request for that matter) or alias the attribute from the base class scope in the derived class scope.

@isedev has a point about avoiding interacting directly with dunderscored pseudo-privates though. Unless you have a compelling need to instrument every single loop through the request listener, you might be better served overriding _handle_request_noblock, which will still let you instrument every request that is processed at a single point, but without having to interact directly with the server state.

نصائح أخرى

By definition, a variable starting with two underscores is 'private' to a given class. In reality, this means Python mangles the variable name by adding an underscore, followed by the defining class name, followed by the actual variable name.

So __is_shut_down, being defined in SocketServer.BaseServer, is actually called _BaseServer__is_shut_down.

Whether you should actually use it is another question, as the authors of BaseServer obviously intended it not to be used.

An example:

class A(object):
    def __init__(self):
        self.__my_variable = 1

a = A()

dir(a)
['_A__my_variable',   <== mangled variable name
 '__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top