我有一个UDP包,每隔2秒就会使用socket读取,然后将UDP数据提取到一个bitarray。
bitarray中的每个位对应于特定条件的真/假值。他们对应的条件是静态的。
我想将每个UDP包中的数据存储在硬盘驱动器上,以便稍后阅读这些数据并及时返回以查看每个条件的真/假状态。我一直在考虑使用日志记录模块执行此操作,但它似乎不是非常有效地存储此类数据。我有可以存储的字节,几乎不占用任何空间。我基本上有60个字节和一个时间戳,可以在很长一段时间内存储每2秒。
我希望能够将这些数据存储在一周的文件中。
我应该使用日志记录模块吗?还是有更有效的方法我还没找到。如果有人能指出一个好的图书馆,那就太好了!
此致
贝伦德
答案 0 :(得分:1)
我还没有找到这样做的图书馆,但您可以使用我为another question撰写的小FileBuffer
课程。数据保存在pickled
state中,带来的磁盘空间更少,尽管数据不再是人类可读的。但由于您的数据是表示布尔值数组的二进制字符串,因此这可能不是问题:
#!/usr/bin/env python3
# coding: utf-8
import os
import pickle
import time
class BinaryFileBuffer:
def __init__(self, basename):
self.basename = basename
@property
def fname(self):
# call other function for better inherit-and-overwrite-behaviour
return self.get_filename()
def get_filename(self):
return '{}.bin'.format(self.basename)
def write(self, data):
with open(self.fname, 'ba') as f:
pickle.dump(data, f)
def write_ts(self, data):
self.write((time.time(), data))
@property
def size(self):
return int(os.path.isfile(self.fname) \
and os.path.getsize(self.fname))
def __iter__(self):
if self.size > 0:
try:
with open(self.fname, 'br') as f:
while True:
yield pickle.load(f)
except EOFError:
return
def flush(self):
if self.size > 0:
os.remove(self.fname)
此数据表示产生的开销非常小,当使用时间戳保存60字节时,您将在磁盘上获得82字节。假设一周内每两秒60字节,你最终得到23.6MB文件,原始数据为17.3MB。
要让此文件"旋转",只需修改文件名即可包含当前年份和周:
class RotatingBinaryFileBuffer(BinaryFileBuffer):
def get_filename(self):
# append year and week number to basename
return '{}_{}.bin'.format( \
self.basename, time.strftime('%Yw%W'))
可能的测试用例如下:
from random import randint
def randstr(strlen):
# include only printable characters
return ''.join(chr(randint(32, 126)) for i in range(strlen))
buf = RotatingBinaryFileBuffer('data')
buf.write_ts(randstr(60))
for item in buf:
print(item)
buflen = max(i for i,_ in enumerate(buf)) + 1
print("\nBytes per entry: {}".format(buf.size/buflen))
这在某种程度上是一个快速的“肮脏的”"自制的解决方案,但也许你有一些用途。