Как мне создать список таймделт в python? - PullRequest
0 голосов
/ 23 ноября 2011

Я искал по этому сайту и видел множество ссылок на дельты времени, но не совсем нашел то, что искал.

По сути, у меня есть список сообщений, полученных сервером связи, и я хочу рассчитать время задержки между каждым сообщением и входящим. Это выглядит так:

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

С этими сообщениями смешаны и другие сообщения, однако я хочу только зафиксировать разницу между сообщениями Out и сообщениями с одинаковым RefID.

Пока что, чтобы разобраться в основном журнале, какие сообщения являются сообщениями, я делал это, но это действительно неэффективно.Мне не нужно каждый раз создавать новые файлы.

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 ]

1 голос
/ 23 ноября 2011

Прежде всего, не записывайте необработанные строки журнала. Во-вторых используйте диктовку.

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 из входной строки и возможную проблему преобразования времени из строки в float и обратно.

На самом деле, простое хранение дельт приведет к путанице, если у вас когда-нибудь будет Рефид, который не принят. Если бы я делал это по-настоящему, я бы сохранил кортеж в значении с начальной датой-временем, конечной датой-временем и дельтой. Для новой записи это будет выглядеть так: (161336.934072,0,0), а после обнаружения принятия это будет выглядеть так: (161336.934072,161336.934159,.000087). Если работа по ведению журнала была непрерывной, скажем, на глобальном сайте электронной коммерции, работающем круглосуточно, то я бы периодически сканировал данные на наличие записей с ненулевой дельтой, сообщал о них и удалял их. Затем я взял бы оставшиеся значения, отсортировал их по дате и времени начала, затем доложил и удалил все, где время начала даты слишком старое, потому что это указывает на неудачные транзакции, которые никогда не завершатся.

Кроме того, на реальном сайте электронной коммерции я мог бы рассмотреть возможность использования чего-то вроде Redis или Memcache в качестве внешнего диктанта, чтобы отчеты и обслуживание могли выполняться другим сервером / приложением.

0 голосов
/ 23 ноября 2011

Эта функция генератора возвращает кортеж, содержащий идентификатор и разницу во временных отметках между сообщениями 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 для in сообщений - это та, которая соответствует refID в 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)
...