views:

40

answers:

2

Here's the code in question:

  class Server(SocketServer.ForkingMixIn, SocketServer.TCPServer):
     __slots__ = ("loaded")

  class Handler(SocketServer.StreamRequestHandler):
     def handle(self):
        print self.server.loaded # Prints "False" at every call, why?
        self.server.loaded = True
        print self.server.loaded # Prints "True" at every call, obvious!

  server = Server(('localhost', port), Handler)
  server.loaded = False

  while True:
     server.handle_request()

Every time a new request comes in, the output I get is "False" followed by "True". What I want is "False" followed by "True" the first time, and "True" followed by "True" henceforth. Why aren't the modifications I made to the variable in the server instance persisting outside the scope of the handler's handle() function?

UPDATED:

So, I try using global variables to achieve what I want:

  loaded = False

  class Server(SocketServer.ForkingMixIn, SocketServer.TCPServer):
     pass

  class Handler(SocketServer.StreamRequestHandler):
     def handle(self):
        global loaded
        print loaded # Prints "False" at every call still, why?
        loaded = True
        print loaded # Prints "True" at every call, obvious!

  def main():
     server = Server(('localhost', 4444), Handler)
     global loaded
     loaded = False

     while True:
        server.handle_request()

  if (__name__ == '__main__'):
     main()

And it still doesn't work, i.e. produces the same output as before. Could anyone please tell me where I'm going wrong?

A: 

Your problem is that SocketServer.ForkingMixin creates a new process for every request. Therefore, every time a new request comes in all your variables get reset to their default state. So essentially no matter what you assign to self.server.loaded it will get reset at the next request. This is also why globals won't work.

If you need a variable to persist between requests you'd best write that data somewhere more, er, persistent =). Essentially, it sounds like you're trying to solve the problem of keeping session variables. There's a million and one ways to do it and depending on your situation, one way might be more pertinent than another. I highly recommend looking at how other Python-based SocketServer applications do it.

Just do a quick google for similar code to yours: "filetype:py SocketServer ForkingMixIn" (one of the first results is CherryPy which I highly recommend looking at).

Dan McDougall
A: 

Forking creates a new process, so you can't modify the server's variables in the original process. Try the ThreadingTCPServer instead:

import SocketServer

class Server(SocketServer.ThreadingTCPServer):
    __slots__ = ("loaded")

class Handler(SocketServer.StreamRequestHandler):
    def handle(self):
        self.server.loaded = not self.server.loaded
        print self.server.loaded # Alternates value at each new request now.

server = Server(('localhost',5000),Handler)
server.loaded = False

while True:
    server.handle_request()
Mark Tolonen
Oh I see. I think this should work. However, I haven't tried it. I just shared the variable between processes using a file and all is well.
Mikhil Masli
Don't forget to accept an answer, if one was acceptable ;^)
Mark Tolonen