[英]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.