如何在python中创建timedeltas列表?

时间:2011-11-23 17:20:08

标签: python datetime timedelta

我一直在搜索这个网站并且已经看到多个时间增量的引用,但还没有找到我正在寻找的东西。

基本上,我有一个由通信服务器接收的消息列表,我想计算每个消息输入和输入之间的延迟时间。它看起来像这样:

161336.934072 - TMsg out: [O] enter order. RefID [123] OrdID [4568]
161336.934159 - TMsg in: [A] accepted. ordID [456]  RefNumber [123] 

与这些消息混合也是其他消息,但是,我只想捕获Out消息和具有相同RefID的消息之间的差异。

到目前为止,要从主日志中找出哪些消息是Tmessages,我一直在这样做,但它真的效率低下。我不需要每次都制作新文件:

big_file = open('C:/Users/kdalton/Documents/Minicomm.txt', 'r')
small_file1 = open('small_file1.txt', 'w')
for line in big_file:
    if 'T' in line: small_file1.write(line)
big_file.close()
small_file1.close()

如何计算两条消息之间的时间增量并从主日志中对这些消息进行排序?

2 个答案:

答案 0 :(得分:1)

首先,不要写出原始日志行。其次使用词典。

tdeltas = {} # this is an empty dict
if "T" in line:
   get Refid number
   if Refid in tedeltas:
      tdeltas[Refid] = timestamp - tdeltas[Refid]
   else:
      tdeltas[Refid] = timestamp

然后在最后,转换为列表并打印

allRefids = sorted(tdeltas.keys())
for k in allRefids:
   print k+": "+tdeltas[k]+" secs"

您可能希望将日期转换为time模块中的datetime个对象,然后使用timedelta对象存储在dict中。可能不值得这项任务,但值得学习如何使用datetime模块。

另外,我已经掩盖了从输入字符串解析Refid,以及将字符串转换为浮点数和返回数字的可能问题。

实际上,如果你有一个不被接受的Refid,只是存储增量将导致混乱。如果我是真的这样做,我会在值中存储一个元组,其中包含start datetime,end datetime和delta。对于新记录,它看起来像这样:(161336.934072,0,0)并且在检测到接受后,它将如下所示:(161336.934072,161336.934159,.000087)。如果记录活动是连续的,比如一个24x7全天候运行的全球电子商务网站,那么我会定期扫描dict以查找具有非零增量的任何条目,报告它们并删除它们。然后我将获取剩余的值,在开始日期时间对它们进行排序,然后报告并删除任何开始日期时间过长的地方,因为这表示将永远无法完成的失败事务。

此外,在真实的电子商务网站中,我可能会考虑使用Redis或Memcache之类的东西作为外部字典,以便其他服务器/应用程序可以完成报告和维护。

答案 1 :(得分:0)

此生成器函数返回一个元组,其中包含id和out和in消息之间的时间戳差异。 (如果你想用时差做一些更复杂的事情,请查看datetime.timedelta)。请注意,这假设消息始终显示在消息之前。

def get_time_deltas(infile):
    entries = (line.split() for line in open(INFILE, "r"))
    ts = {} 
    for e in entries:
        if len(e) == 11 and " ".join(e[2:5]) == "TMsg out: [O]":
            ts[e[8]] = e[0]   # store timestamp for id
        elif len(e) == 10 and " ".join(e[2:5]) == "TMsg in: [A]":   
            in_ts, ref_id = e[0], e[9]
            # Raises KeyError if out msg not seen yet. Handle if required.
            out_ts = ts.pop(ref_id)   # get ts for this id
            yield (ref_id[1:-1], float(in_ts) - float(out_ts))

您现在可以从中获取一个列表:

>>> INFILE = 'C:/Users/kdalton/Documents/Minicomm.txt'
>>> list(get_time_deltas(INFILE))
[('123', 8.699999307282269e-05), ('1233', 0.00028700000257231295)]

或将其写入文件:

>>> with open("out.txt", "w") as outfile:
...     for id, td in get_time_deltas(INFILE):
...          outfile.write("Msg %s took %f seconds\n", (id, td))

或将其链接到更复杂的工作流程。


更新

(回应查看实际数据)

请改为尝试:

def get_time_deltas(infile):
    entries = (line.split() for line in open(INFILE, "r"))
    ts = {} 
    for e in entries:
        if " ".join(e[2:5]) == "OuchMsg out: [O]":
            ts[e[8]] = e[0]   # store timestamp for id
        elif " ".join(e[2:5]) == "OuchMsg in: [A]":   
            in_ts, ref_id = e[0], e[7]
            out_ts = ts.pop(ref_id, None)   # get ts for this id
            # TODO: handle case where out_ts = None (no id found)
            yield (ref_id[1:-1], float(in_ts) - float(out_ts))

INFILE = 'C:/Users/kdalton/Documents/Minicomm.txt'
print list(get_time_deltas(INFILE))

此版本的变化:

  • 字段数量不在发布的示例输入中说明。根据条目号
  • 删除了支票 对于ordID条消息,
  • inrefID条消息中的out匹配
  • 使用OuchMsg代替TMsg

更新2

获得增量的平均值:

deltas = [d for _, d in get_time_deltas(INFILE)] 
average = sum(deltas) / len(deltas)

或者,如果您之前已生成包含所有数据的列表,我们可以重复使用它而不是重新分析文件:

data = list(get_time_deltas(INFILE))
# .. use data for something some operation ...

# calculate average using the list
average = sum(d for _, d in data) / len(data)