You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向Python的TCPServer Handler类传递参数?

向socketserver的Handler传递文件名参数的合理方案

原代码实现了客户端读取文件内容发送到TCP服务端,服务端打印接收数据的功能。现在要把服务端的打印逻辑改成写入文件,又不想用硬编码或全局变量,下面是几个靠谱的实现方案:

方案1:利用TCPServer的自定义属性传递参数

TCPServer的构造函数会把额外的关键字参数绑定到自身实例上,Handler类可以通过self.server访问到服务端实例,进而拿到传递的参数。

修改后的完整代码:

from socket import socket, AF_INET, SOCK_STREAM
from socketserver import BaseRequestHandler, TCPServer
from threading import Thread

HOST = "localhost"
PORT = 10101
ADDR = HOST, PORT
RECVBUF = 4096
SENDBUF = RECVBUF // 2
INPFILE = "inputfile.txt"
OUTPUTFILE = "outputfile.txt"  # 目标输出文件


class MyHandler(BaseRequestHandler):
    def handle(self):
        # 从服务端实例中获取输出文件名
        with open(self.server.output_file, "ab") as outfile:
            while data := self.request.recv(RECVBUF):
                outfile.write(data)


def server(tcpserver: TCPServer):
    tcpserver.serve_forever()


if __name__ == "__main__":
    with open(INPFILE, "rb") as indata:
        # 初始化TCPServer时传入自定义属性output_file
        with TCPServer(ADDR, MyHandler, output_file=OUTPUTFILE) as tcpserver:
            (t := Thread(target=server, args=[tcpserver])).start()
            with socket(AF_INET, SOCK_STREAM) as s:
                s.connect(ADDR)
                while chunk := indata.read(SENDBUF):
                    s.sendall(chunk)
            tcpserver.shutdown()
            t.join()

方案2:用工厂函数动态生成带参数的Handler类

写一个工厂函数,接收文件名参数后,返回一个已经绑定该参数的Handler子类,利用闭包特性让内部类能访问到外部参数。

修改后的完整代码:

from socket import socket, AF_INET, SOCK_STREAM
from socketserver import BaseRequestHandler, TCPServer
from threading import Thread

HOST = "localhost"
PORT = 10101
ADDR = HOST, PORT
RECVBUF = 4096
SENDBUF = RECVBUF // 2
INPFILE = "inputfile.txt"
OUTPUTFILE = "outputfile.txt"


def create_handler(output_file):
    class CustomHandler(BaseRequestHandler):
        def handle(self):
            with open(output_file, "ab") as outfile:
                while data := self.request.recv(RECVBUF):
                    outfile.write(data)
    return CustomHandler


def server(tcpserver: TCPServer):
    tcpserver.serve_forever()


if __name__ == "__main__":
    with open(INPFILE, "rb") as indata:
        # 通过工厂函数创建带参数的Handler类
        MyHandler = create_handler(OUTPUTFILE)
        with TCPServer(ADDR, MyHandler) as tcpserver:
            (t := Thread(target=server, args=[tcpserver])).start()
            with socket(AF_INET, SOCK_STREAM) as s:
                s.connect(ADDR)
                while chunk := indata.read(SENDBUF):
                    s.sendall(chunk)
            tcpserver.shutdown()
            t.join()

方案3:自定义TCPServer子类封装参数

如果需要传递多个参数或者要扩展服务端功能,自定义TCPServer子类,把参数封装在子类属性中,Handler同样通过self.server访问。

修改后的完整代码:

from socket import socket, AF_INET, SOCK_STREAM
from socketserver import BaseRequestHandler, TCPServer
from threading import Thread

HOST = "localhost"
PORT = 10101
ADDR = HOST, PORT
RECVBUF = 4096
SENDBUF = RECVBUF // 2
INPFILE = "inputfile.txt"
OUTPUTFILE = "outputfile.txt"


class CustomTCPServer(TCPServer):
    def __init__(self, server_address, RequestHandlerClass, output_file, bind_and_activate=True):
        self.output_file = output_file
        super().__init__(server_address, RequestHandlerClass, bind_and_activate)


class MyHandler(BaseRequestHandler):
    def handle(self):
        with open(self.server.output_file, "ab") as outfile:
            while data := self.request.recv(RECVBUF):
                outfile.write(data)


def server(tcpserver: CustomTCPServer):
    tcpserver.serve_forever()


if __name__ == "__main__":
    with open(INPFILE, "rb") as indata:
        with CustomTCPServer(ADDR, MyHandler, OUTPUTFILE) as tcpserver:
            (t := Thread(target=server, args=[tcpserver])).start()
            with socket(AF_INET, SOCK_STREAM) as s:
                s.connect(ADDR)
                while chunk := indata.read(SENDBUF):
                    s.sendall(chunk)
            tcpserver.shutdown()
            t.join()

内容的提问来源于stack exchange,提问作者jackal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:19:52