How do I modify variables in the SocketServer server instance from within a RequestHandler handler instance in Python?
-
28-09-2019 - |
Question
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?
Solution
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()
OTHER TIPS
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).