Nick
Nick

Reputation: 185

Dynamic nested dictionaries

Just to begin I know there are a couple similarly-titled questions on here, but none are explained quite this way nor is the problem scope the same.

I want to add nested dictionary entries dynamically.

The use case is thus: I have a python script that is monitoring the network. A dictionary is created for each observed IP protocol (tcp, udp, icmp) that is observed. Then a sub-dictionary is created with a key that is the destination port (if one exists) for each of these IP protocols (80, 443, etc.) (note it doesn't matter whether it sees the server port as the source or destination, but normally servers are the destination so I picked HTTP and HTTPS as examples). For each of these destination ports a key is created corresponding to the server IP (e.g., the IP for www.google.com). And then another dictionary with the timestamp the session was first observed as the key and the data/value for the key being the client's IP.

However, I want need this to be populated as time goes on since I won't have the data before execution nor at initialization.

The output would look something akin to:

{  'icmp' :
   {  'echo-request' :
       {  '<ip_of_www.google.com>' :
           {   '<timestamp>' : <some_client_ip> }
       }
      'echo-reply' :
       {  '<ip_of_www.google.com>' :
           {   '<timestamp>' : <some_client_ip> }
       }
   }
   'tcp' :
   {
      '80' 
       {  '<ip_of_www.google.com>' :
           {   '<timestamp>' : <some_client_ip> }
           {   '<timestamp>' : <some_client_ip> }
       }
      '443' 
       {  '<ip_of_encrypted.google.com>' :
           {   '<timestamp>' : <some_client_ip> }
           {   '<timestamp>' : <some_client_ip> }
           {   '<timestamp>' : <some_client_ip> }
           {   '<timestamp>' : <some_client_ip> }
       }
   }
}

Thanks!

Upvotes: 0

Views: 1475

Answers (1)

Anton Zuenko
Anton Zuenko

Reputation: 761

Here you are:

def set_nested(dict, value, *path):
    for level in path[:-1]:
        dict = dict.setdefault(level, {})

    dict[path[-1]] = value


d = {}

set_nested(d, '127.0.0.1', 'icmp', 'echo', 'google.com', '1 dec 2014')
set_nested(d, '127.0.0.1', 'icmp', 'echo', 'google.com', '2 dec 2014')
set_nested(d, '127.0.0.1', 'icmp', 'echo', 'yahoo.com', '2 dec 2014')
set_nested(d, 'error', 'udp')

from pprint import pprint
pprint(d)

Output:

{'icmp': {'echo': {'google.com': {'1 dec 2014': '127.0.0.1',
                                  '2 dec 2014': '127.0.0.1'},
                   'yahoo.com': {'2 dec 2014': '127.0.0.1'}}},
 'udp': 'error'}

I'd also suggest you to have a look at json and tinydb if you want to store and query results.

Upvotes: 5

Related Questions