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

发布于 2024-10-07 03:34:31 字数 1134 浏览 5 评论 0原文

我在获取 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()

然而这段代码可以工作,任何想法

data, address = sock.recvfrom(8192)
rec = logging.makeLogRecord(cPickle.loads(data[4:]))
logger.handle(rec)

问候

I am having a problem getting the example code shown in the python docs for the logging DatagramHandler, the code shown below gives EOFError exceptions on every datagram received.

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

However this code works, any ideas

data, address = sock.recvfrom(8192)
rec = logging.makeLogRecord(cPickle.loads(data[4:]))
logger.handle(rec)

Regards

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寄与心 2024-10-14 03:34:31

我希望您的第一个 recv(4) 调用会复制数据报中的前四个字节,然后将数据包的其余部分扔到地板上;第二次调用 recv 然后发现没有任何内容可读取并返回 EOFError。从我的系统的 udp(7) 联机帮助页中:

   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.

尝试读入整个数据报,获取前四个字节的长度,然后处理存储整个数据报的数组子集。

当然,如果你的pickles不完全适合连接的MTU,它会可能永远不会按您的预期工作。

I expect your first recv(4) call copies the first four bytes out of your datagram and then throws the rest of the packet on the floor; your second call to recv then finds nothing to read and returns EOFError. From my system's 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.

Try reading in the entire datagram, grabbing the length out of the first four bytes, and then working on the subset of the array that stores the entire datagram.

Of course, if your pickles don't fit entirely within the MTU of the connection, it'll probably never work as you intend.

我不咬妳我踢妳 2024-10-14 03:34:31

完整的 MWA 看起来像这样。

请注意,我们只是丢弃前四个字节(pickle-data 的大小),这些字节的存在是因为 DatagramHandler 继承了在 TCP 模式下运行的 SocketHandler。由于我们使用的是 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 )

改编自 https://docs.python 中的 TCP 示例。 org/3/howto/logging-cookbook.html#logging-cookbook

A complete MWA looks something like this.

Notice we just discard the first four bytes (the size of the pickle-data), these exist because DatagramHandler inherits SocketHandler, which operates in TCP mode. Since we're on UDP we can just read to the end of the packet however. As Sarnold points out, if the data doesn't fit into a packet, we'd need a better solution and, since UDP can miss packets, that would require server side customisations. Perhaps the simplest server-side solution would just to be to split up any messages so we don't go over the limit in the first place!

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 )

Adapted from the TCP example at https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbook.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文