0

hey i want to put two values into one dict and am not sure how to achieve this. i want it to look like this

{'Feb  7': {'89.249.209.92': 15},
 'Feb  8': {'66.30.90.148': 14, '72.153.93.203': 14, '92.152.92.123': 5},
 'Jan 10': {'213.251.192.26': 13, '218.241.173.35': 15}}

here my current code and what i currently getting in dict

desc_ip = {}

count_ip = 0

    for line in myfile:
        if 'Failed password for' in line:

            line_of_list = line.split()

            ip_address = ' '.join(line_of_list[0:2])
            ip_address = line_of_list[-4]
            if ip_address in desc_ip:
                count_ip = desc_ip[ip_address]
                count_ip = count_ip +1
                desc_ip[ip_address] = count_ip
                #zero out the temporary counter as a precaution
                count_ip =0
            else:
                desc_ip[ip_address] = 1

    for ip in desc_ip.keys():
        print ip ,' has', desc_ip[ip] , ' attacks'

here my current dict

{'213.251.192.26': 13,
 '218.241.173.35': 15,
 '66.30.90.148': 14,
 '72.153.93.203': 14,
 '89.249.209.92': 15,
 '92.152.92.123': 5}

here a few lines from the file

Jan 10 09:32:09 j4-be03 sshd[3876]: Failed password for root from 218.241.173.35 port 47084 ssh2
Feb  7 17:19:24 j4-be03 sshd[10740]: Failed password for root from 89.249.209.92 port 46752 ssh2
  • Could you post a few lines of example input (`myfile`), to make it easier to play with your code-snippet? – dbr Mar 12 '12 at 13:04
  • 1
    Check out the following: [Python nested dictionaries][1] [1]: http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python – Colin Swelin Mar 12 '12 at 13:09

4 Answers4

2
date = 'Feb  7'
ip = '89.249.209.92'
count = 15

d = {}
d[date] = {ip: count}
Janne Karila
  • 21,241
  • 4
  • 47
  • 86
1

You need a dict of dicts, so use the dates as keys and create a dict for each date.

alexis
  • 43,587
  • 14
  • 86
  • 141
0

A very extensible answer uses the AutoVivification class, as shown by user Nosklo:

class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

With some sample data:

sample_text = '''Feb 7 :  89.249.209.92
Feb 7 :  89.249.209.92
Feb 7 :  89.249.209.92
Feb 8 :  89.249.209.92
Jan 10 :  218.241.173.35'''

A quick read into the data gives:

A = AutoVivification()

for line in sample_text.split('\n'):
    date, IP = map(str.strip,line.split(':'))
    if IP not in A[date]: A[date][IP] = 0
    A[date][IP] += 1


>>>> {'Jan 10': {'218.241.173.35': 1}, 'Feb 8': {'89.249.209.92': 1}, 'Feb 7': {'89.249.209.92': 3}}

Note that the AutoVivification class does not know the depth of your nesting. Therefore you need to set the depth by explicitly setting a value for the key as in A[date][IP] = 0.

Community
  • 1
  • 1
Hooked
  • 70,732
  • 35
  • 167
  • 242
0

I assumed the date was present in each line:

>>> sample_text = '''Feb 7 :  Failed password for 89.249.209.92
Feb 7 :  Failed password for 89.249.209.92
Feb 7 :  Failed password for 89.249.209.92
Feb 8 :  Failed password for 89.249.209.92
Jan 10 :  Failed password for 218.241.173.35'''
>>> desc_ip = {}
>>> for line in sample_text.split('\n'):
    if 'Failed password for' in line:
        line_of_list = line.split()
        ip_address = line_of_list[6]
        date = ' '.join(line_of_list[0:2])
        if not date in desc_ip:
            desc_ip[date] = {}
        if not ip_address in desc_ip[date]:
            desc_ip[date][ip_address] = 0
        desc_ip[date][ip_address] += 1


>>> desc_ip
{'Jan 10': {'218.241.173.35': 1}, 'Feb 8': {'89.249.209.92': 1}, 'Feb 7': {'89.249.209.92': 3}}
>>> 

I could use defaultdict in order to avoid tests such as if not date in desc_ip, but here we would need a defaultdict of defaultdict (like desc_ip = defaultdict(lambda : defaultdict(int))) and IMHO that decreases readability.

Emmanuel
  • 12,525
  • 9
  • 44
  • 66