-2

我正在读取具有以下格式的文本文件:

0.000 ff:dd ff:ff 4 126 48000  
0.001 sd:fg er:sd 5 125 67000  
0.002 qw:er ff:dd 5 127 90000  
0.003 xc:sd ff:dd 5 127 90000  
0.004 io:uy gh:ij 4 126 56000  

在第四列中,4 表示请求,5 表示响应。如果该行代表一个请求,我应该形成一个以第二列作为键的字典。
如果第四列的值为 5,则表示该行对应于响应。在这种情况下,查看该响应的第 3 列,如果该第 3 列作为字典键存在,则添加第 2 列作为该对应键的值。

在上面的例子中,期望的结果是:

{'ff:dd': 1, 2, 48000, qw:er, xc:sd}, {'io:uv': 1, 0, 56000}  

对于ff:dd,1表示来自ff:dd的请求只有1个;2 表示对 ff:dd 有 2 个响应,48000 是 ff:dd 对应的请求的第 6 列值。我希望你明白这个问题。请要求任何澄清。
对于 io:uv,由于没有响应,1 表示请求数,0 表示响应数,56000 是该请求的第 6 列值。
我这样做是为了分析网络流量。

我不知道如何动态添加值。如果有固定数量的值,我可以管理,但这是一个棘手的情况。我使用python2.6。非常感谢您的帮助。提前致谢!

4

3 回答 3

0

让我们尝试一种使事情变得更容易的数据结构。

如果我对您的理解正确,您希望这些地址成为您字典的键,并且您希望存储在这些键下的数据是:

  • 从该地址发送的请求数
  • 在该地址收到的请求数
  • 向该地址发送请求的地址列表

这可能最好像这样格式化:

{address:[sent, recv, [address, address, ...]], ...}

因此,您可以像这样阅读文本文件:

with open('myfile.txt', 'r') as myfile:
    dct = {}
    for line in myfile:
        splt = line.split()

现在您正在遍历文件中的每一行并按列拆分它。接下来,我们要确定它是请求还是响应:

        if splt[3] == '4': # request
            # we're about to fill this in
        elif split[3] == '5': # response
            # we're about to fill this in

这将检查第 4 列中的'4''5'。如果您在那里有另一个值(即您的数据格式不正确),您将遇到问题。

现在,如果我们正在处理请求,我们将执行以下操作:

            if splt[1] not in dct:
                dct[splt[1]] = [1, 0, []]
            else:
                dct[splt[1]][0] += 1

这会将发送的请求数增加 1;如果地址还没有在字典中,那么我们添加它。我们splt[1]在这里使用是因为我们谈论的是发送者的地址,而不是接收者的地址。

如果我们正在处理响应,我们当然会采取不同的行动。我在这里假设您永远不会在没有首先提出请求的情况下发送响应......但以防万一,我已经把那个案例放在那里,pass只是忽略它。由你决定你想用它做什么......

            if splt[2] not in dct:
                pass
            else:
                dct[splt[2]][1] += 1
                if splt[1] not in dct[splt[2]][2]:
                    dct[splt[2]][2].append(splt[1])

在这里,我们将收到的响应数加 1,并将响应者的地址添加到我们的列表中。我们使用splt[2]作为 key 是因为我们谈论的是接收者的地址,而不是发送者的地址。

这应该是你想要完成的事情的关键——虽然我不明白第四列和第五列是做什么的,所以我省略了它们。

于 2013-06-21T22:07:29.520 回答
0

让我们首先确保我们清楚字典是什么以及它可以用来做什么(希望我不要把脚放在嘴里——我自己对 Python 还很陌生)。

关于字典

在 Python 中, a将单个键dict映射到单个值。您可以根据需要阅读文档,但这里的一个问题是您似乎希望将单个键映射到所需结果中的多个值:

{'ff:dd': 1, 2, 48000, qw:er, xc:sd}, {'io:uv': 1, 0, 56000}

这显示了两个字典。查看第一个字典, 仅{'ff:dd': 1,将键映射'ff:dd'到值1;逗号表示,继续下一key:value对。所以其余的被解释为键248000映射到无值(抛出SyntaxError),未定义的名称qwxc映射到未定义的名称er和(如果你走那么远sd就会抛出)。NameError您可能意味着 forqw:erxc:sdto 是字符串,在这种情况下,它们将被视为未映射到任何 value 的键,例如数字248000之前的数字。您可以在 shell 中对此进行测试:

>>> {'key':'value'}               # A dict with one key, that has a value
{'key': 'value'}

>>> {'key'}                       # Curly braces can make a dict or a set
set(['key'])

>>> {'key1':'val1', 'key2'}       # A dict needs to have values for each key
SyntaxError: invalid syntax       

>>> {'key1':'val1', 'key2':}      # Even an "empty" value has to be explicit
SyntaxError: invalid syntax

如果您出于某种原因想要在知道它们的值之前定义您的键,则使用零或空字符串可能是可行的,但“正确”的方法可能是使用dict.fromkeys()

>>> {'key1':None, 'key2':'', 'key3':0}     # One of these might do the job...
{'key3': 0, 'key2': '', 'key1': None}

>>> dict.fromkeys(['key1','key2', 'key3']) # ...but this is probably better.
{'key3': None, 'key2': None, 'key1': None}

(作为旁注,您可能不想谈论“附加”到字典。这是您对有序列表所做的事情,例如 by mylist.append(myvalue)。字典没有append()方法;您所做的是设置一个键,如果键不存在,则创建它。“追加”表示添加到末尾,但字典是无序的,因此它们没有“结尾”。)

存储您的数据

现在,我将对您要尝试做什么做一个假设qw:er, xc:sd,因为您的问题并不完全清楚。我的假设是,您只是想要一个发送到的响应列表'ff:dd'。如果你愿意,你可以做其他事情,但在这个假设下,我会尝试阐明如何做一些你想做的事情。看起来您想要的结果类似于:

traffic = { 'ff:dd': { 'reqfrom':1, 'respto':2, 'reqvals':[48000],
                       'responders':['qw:er', 'xc:sd'] },
            'io:uv': { 'reqfrom':1, 'respto':0, 'reqvals':[56000],
                       'responders':[] }
           }

在字典的顶层traffic,有两个键:'ff:dd''io:uv'。每个键的值是另一个字典,因此您可以访问来自键的请求数、对键的响应以及与该特定地址关联的其他值,如下所示:

>>> traffic['io:uv']['reqfrom']         # How many requests from 'io:uv'?
1

>>> traffic['ff:dd']['responders']      # What are the responses to 'ff:dd'?
['qw:er', 'xc:sd']

那么,如何动态存储这些值呢?通常,您只需为键分配一个值,例如mydict['key'] = 'value'. 如果 key 已经存在,则 key 的 value 将被更新;如果没有,键值对将被添加到字典中。但是由于您的第一个键的值本身就是字典,所以有点棘手。

尝试这个...

这是使用上述假设结构的一种可能方法的示例。我不会详细介绍,因为更有经验的 Python 用户可能会向您展示做同样事情的更好方法。试试这个代码的大小 - 运行它,阅读它,打破它等。你应该能够弄清楚如何根据你的目的调整它。

traffic = {}

packets = (('0.000', 'ff:dd', 'ff:ff', '4', '126', '48000'),
           ('0.001', 'sd:fg', 'er:sd', '5', '125', '67000'),
           ('0.002', 'qw:er', 'ff:dd', '5', '127', '90000'),
           ('0.003', 'xc:sd', 'ff:dd', '5', '127', '90000'),
           ('0.004', 'io:uv', 'gh:ij', '4', '126', '56000'))

def record_packet(packet):
    if packet[3] == '4':        # Request

        # Set up the key-value if it doesn't exist
        if packet[1] not in traffic:
            traffic[packet[1]] = {'reqfrom':0,
                                  'respto':0,
                                  'reqvals':[],
                                  'responders':[]
                                  }

        traffic[packet[1]]['reqfrom'] += 1
        traffic[packet[1]]['reqvals'].append(packet[5])

    elif packet[3] == '5':      # Response

        # Record the response IFF there has been a request
        if packet[2] in traffic:
            traffic[packet[2]]['respto'] += 1
            traffic[packet[2]]['responders'].append(packet[1])

    else:
        # Handle weirdness here
        pass

for packet in packets:
    record_packet(packet)

for key in traffic:
    for item in traffic[key]:
        print "traffic['{0}']['{1}'] has value: {2}".format(key, item, traffic[key][item])
于 2013-06-21T21:41:46.927 回答
0

使用字典,键是字符串,值是包含(请求、响应、第 6 列、[响应键列表])的元组

于 2013-06-21T18:59:32.257 回答