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

如何用Python实现客户端打印服务端监测到的日志变更(模拟tail -f)

问题根因
    1. Tail类默认回调是sys.stdout.write,初始化时未传入发送到socket的回调函数,所有日志内容直接输出到服务端控制台,没有发往客户端
    1. follow()方法是永久阻塞的死循环,无任何返回值,你调用clientsocket.send(bytes(py_tail.follow(10),"utf-8"))这行代码永远无法获得要发送的内容,也不会执行后续逻辑
    1. 客户端代码中msg.decode("utf-8")未保存解码结果,直接打印原始bytes对象,就算收到数据显示格式也错误
    1. 服务端单线程逻辑只能同时处理一个客户端连接,阻塞在follow逻辑后无法响应其他操作
修复后代码

server.py

import socket
import sys
import threading

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1243))
s.listen(5)

class Tail():
    def __init__(self,file_name,callback=sys.stdout.write):
        self.file_name = file_name
        self.callback = callback
    def follow(self,n):
        try:
            with open(self.file_name) as f:
                self._file = f
                self.showLastLine(n)
                self._file.seek(0,2)
                while True:
                    line = self._file.readline()
                    if line:
                        self.callback(line)
        except Exception as e:
            print('Failed to open the file. See if the file does not exist or if there is a problem with permissions')
            print(e)
    
    def showLastLine(self, n):
        last_lines = self._file.readlines()[-10:]
        for line in last_lines:
            self.callback(line)

# 处理单个客户端连接的函数
def handle_client(clientsocket):
    # 定义回调函数,收到新日志直接发给客户端
    def send_to_client(line):
        try:
            clientsocket.send(line.encode("utf-8"))
        except:
            # 客户端断开连接时结束
            clientsocket.close()
            return
    py_tail = Tail('log.log', callback=send_to_client)
    py_tail.follow(10)

while True:
    clientsocket, address = s.accept()
    print(f"新客户端连接:{address}")
    # 每个连接单独开线程处理,不阻塞主进程
    client_thread = threading.Thread(target=handle_client, args=(clientsocket,))
    client_thread.daemon = True
    client_thread.start()

client.py

import socket
import sys

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1243))

while True:
    msg = s.recv(1024)
    if not msg:
        # 服务端断开连接时退出
        break
    # 保存解码后的内容再打印
    content = msg.decode("utf-8")
    print(content, end='')
测试说明

先启动服务端,再启动客户端,此时客户端会先打印log.log的最后10行内容,之后你新增的日志内容会实时推送到客户端打印。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:54:07