Python日志记录数据报处理程序

Python日志记录数据报处理程序,python,logging,handler,datagram,Python,Logging,Handler,Datagram,我在获取python文档中所示的用于日志记录DatagramHandler的示例代码时遇到问题,下面所示的代码在接收到的每个数据报上都给出了EOFError异常 import socket import logging import cPickle import struct import sys sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) sock.bind (('localhost', 9000)) handler =

我在获取python文档中所示的用于日志记录DatagramHandler的示例代码时遇到问题,下面所示的代码在接收到的每个数据报上都给出了EOFError异常

import socket
import logging
import cPickle
import struct
import sys

sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
sock.bind (('localhost', 9000))

handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("UDP LogViewer %(asctime)s %(message)s"))
logger = logging.getLogger("Test")
logger.addHandler(handler)

try:
    while True:
        dgram_size = sock.recv(4)
        if len(dgram_size) < 4:
            break
        slen = struct.unpack(">L", dgram_size)[0]
        data = sock.recv(slen)

        while len(data) < slen:
            data = data + sock.recv(slen - len(data))

        try:
            obj = cPickle.loads(data)
            record = logging.makeLogRecord(obj)
            logger.handle(record)
        except:
            print "exception", sys.exc_info()[0]



finally:
    sock.close()

关于

我希望您的第一个
recv(4)
调用会将数据报的前四个字节复制出来,然后将数据包的其余部分扔到地板上;您对
recv
的第二次调用没有找到要读取的内容并返回EOFError。从我的系统的
udp(7)
manpage:

   All receive operations return only one packet.  When the packet
   is smaller than the passed buffer, only that much data is
   returned; when it is bigger, the packet is truncated and the
   MSG_TRUNC flag is set.  MSG_WAITALL is not supported.
尝试读取整个数据报,从前四个字节中提取长度,然后处理存储整个数据报的数组子集


当然,如果您的pickle不完全适合连接的范围,它可能永远不会像您所希望的那样工作。

完整的MWA看起来像这样

注意,我们只是丢弃了前四个字节(pickle数据的大小),它们的存在是因为
DatagramHandler
继承了
SocketHandler
,后者在TCP模式下运行。但是,由于我们使用UDP,所以我们只能读取到数据包的末尾。正如Sarnold所指出的,如果数据不能装入数据包,我们需要一个更好的解决方案,而且由于UDP可能会丢失数据包,因此需要服务器端自定义。也许最简单的服务器端解决方案就是拆分任何消息,这样我们一开始就不会超过限制

import socketserver
import socket
import pickle
import logging

class MyDatagramRequestHandler( socketserver.DatagramRequestHandler ):
    def handle( self ):
        try:
            while True:
                chunk = self.socket.recv( 2048 )
                chunk = chunk[4:]
                obj = self.unPickle( chunk )
                record = logging.makeLogRecord( obj )
                self.on_handle( record )
        except socket.timeout:
            pass

    def unPickle( self, data ):
        return pickle.loads( data )
        
    def on_handle( self, record: logging.LogRecord ):
        # do something, e.g.
        logger = logging.getLogger( record.name )
        logger.handle( record )

改编自上的TCP示例。

谢谢sarnold,我将为您热烈欢呼sarnold,非常感谢
import socketserver
import socket
import pickle
import logging

class MyDatagramRequestHandler( socketserver.DatagramRequestHandler ):
    def handle( self ):
        try:
            while True:
                chunk = self.socket.recv( 2048 )
                chunk = chunk[4:]
                obj = self.unPickle( chunk )
                record = logging.makeLogRecord( obj )
                self.on_handle( record )
        except socket.timeout:
            pass

    def unPickle( self, data ):
        return pickle.loads( data )
        
    def on_handle( self, record: logging.LogRecord ):
        # do something, e.g.
        logger = logging.getLogger( record.name )
        logger.handle( record )