簡體   English   中英

Python 日志記錄數據報處理程序

[英]Python logging datagram 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()

但是這段代碼有效,任何想法

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

問候

我希望您的第一個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.

嘗試讀入整個數據報,從前四個字節中獲取長度,然后處理存儲整個數據報的數組子集。

當然,如果您的泡菜不完全適合連接的MTU ,它可能永遠不會按您的預期工作。

一個完整的 MWA 看起來像這樣。

注意我們只是丟棄了前四個字節(pickle-data 的大小),這些存在是因為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 )

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM