如何在Python中从RequestHandler处理程序实例中修改SocketServer服务器实例的变量?

3 投票
2 回答
2114 浏览
提问于 2025-04-16 05:03

这是我遇到的代码:

  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()

每次有新请求进来的时候,我得到的输出是 False 然后是 True。我想要的结果是第一次输出 False 然后是 True,之后的请求都输出 True 然后是 True

为什么我在服务器实例中对变量所做的修改没有在处理函数 handle() 的范围之外保留呢?

更新:

所以,我尝试使用全局变量来实现我想要的效果:

  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()

但这仍然不行,也就是说,输出和之前一样。谁能告诉我我哪里出错了吗?

2 个回答

2

你的问题在于,SocketServer.ForkingMixin 每次处理请求时都会创建一个新进程。因此,每当有新请求到来时,所有的变量都会被重置为默认状态。所以,不管你把什么赋值给 self.server.loaded,它在下一个请求到来时都会被重置。这也是为什么全局变量不起作用的原因。

如果你需要一个变量在多个请求之间保持不变,最好把这些数据存储在一个更“持久”的地方。实际上,听起来你是在尝试解决保持会话变量的问题。有很多种方法可以做到这一点,根据你的具体情况,有些方法可能更合适。我强烈建议你看看其他基于 Python 的 SocketServer 应用是怎么做的。

你可以快速在谷歌上搜索类似的代码:“filetype:py SocketServer ForkingMixIn”(搜索结果中有一个是 CherryPy,我非常推荐你去看看)。

4

分叉(Forking)会创建一个新的进程,所以你不能在原来的进程中修改服务器的变量。你可以试试使用 ThreadingTCPServer:

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()

撰写回答