문제

I'm confused as to how to send a variable to a TCPHandler using SocketServer.TCPServer in python..

HOST, PORT = hosts[0], args.port
server = SocketServer.TCPServer((HOST, PORT), METCPHandler)
server.serve_forever()

Which calls:

class METCPHandler(SocketServer.BaseRequestHandler):           
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0])
        r = MExpressHandler(self.data, False)

But I want to pass a debug boolean to MExpressHandler.. so

HOST, PORT = hosts[0], args.port
server = SocketServer.TCPServer((HOST, PORT), METCPHandler(debug))
server.serve_forever()

Fails. Whats the correct way of doing this? Do I have to recreate a whole TCPHandler over-ridding __init__?

도움이 되었습니까?

해결책

Trust your instincts, the correct way is indeed to subclass TCPServer and override the __init__ method, but Python makes this very easy!

import SocketServer

class DebugTCPServer(SocketServer.TCPServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, debug=True):
        self.debug = debug
        SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=True)

class DebugMETCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        # self.server is an instance of the DebugTCPServer
        DEBUG = self.server.debug
        self.data = self.request.recv(1024).strip()
        if DEBUG:
            print "{} wrote:".format(self.client_address[0])
        r = MExpressHandler(self.data, False)


server = DebugTCPServer((HOST, PORT), DebugMETCPHandler, debug=True)

or since we specified debug=True as the default:

server = DebugTCPServer((HOST, PORT), DebugMETCPHandler)

다른 팁

As I proposed in this post already, it is possible to do it without sub-classing the TCPServer. It is in fact more concise and generic.

You can give parameters to your handler this way:

class METCPHandler(SocketServer.BaseRequestHandler):
  def __init__(self, debug):
    self.debug = debug

  def __call__(self, request, client_address, server):
    h = METCPHandler(self.debug)
    SocketServer.StreamRequestHandler.__init__(h, request, client_address, server)

You can now give an instance of your handler to the TCPServer:

SocketServer.TCPServer((HOST, PORT), METCPHandler(True))

The TCPServer normally creates a new instance of METCPHandler per request but in this case, the __call__ method will be called instead of the constructor (it is already an instance.)

In the call method, I explicitly make a copy of the current METCPHandler and pass it to the super constructor to conform to the original logic of "one handler instance per request".

It is worth having a look at the SocketServer module to understand what happens here: https://github.com/python/cpython/blob/2.7/Lib/SocketServer.py

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top