Python, is there a easier way to add values to a default key?
Question: The program I am working does the following:

  * Grabs stdout from a .perl program
  * Builds a nested dict from the output

I'm using the AutoVivification approach found
[here](http://stackoverflow.com/questions/635483/what-is-the-best-way-to-
implement-nested-dictionaries-in-python) to build a default nested dictionary.
I'm using this method of defaultdict because it's easier for me to follow as a
new programmer.

I'd like to add one key value to a declared key per pass of the `for line` in
the below code. Is there a easier way to add values to a key beyond making a
`[list]` of values then adding said values as a group?

    
    
    import pprint
    
    class Vividict(dict):
        def __missing__(self, key):
            value = self[key] = type(self)()
            return value
    
    reg = 'NtUser'
    od = Vividict()
    od[reg]
    
    def run_rip():
        os.chdir('/Users/ME/PycharmProjects/RegRipper2.8')  # Path to regripper dir
        for k in ntDict:
            run_command = "".join(["./rip.pl", " -r 
                                  /Users/ME/Desktop/Reg/NTUSER.DAT -p ", str(k)])  
            process = subprocess.Popen(run_command,
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            out, err = process.communicate()  # wait for the process to terminate
            parse(out)
            # errcode = process.returncode // used in future for errorcode checking
            ntDict.popitem(last=False)
    
    def parse(data):
        pattern = re.compile('lastwrite|(\d{2}:\d{2}:\d{2})|alert|trust|Value')
        grouping = re.compile('(?P<first>.+?)(\n)(?P<second>.+?)
                             ([\n]{2})(?P<rest>.+[\n])', re.MULTILINE | re.DOTALL)
        if pattern.findall(data):
            match = re.search(grouping, data)
            global first
            first = re.sub("\s\s+", " ", match.group('first'))
            od[reg][first]
            second = re.sub("\s\s+", " ", match.group('second'))
            parse_sec(second)
    
    def parse_sec(data):
        pattern = re.compile(r'^(\(.*?\)) (.*)$')
        date = re.compile(r'(.*?\s)(.*\d{2}:\d{2}:\d{2}.*)$')
        try:
            if pattern.match(data):
                result = pattern.match(data)
                hive = result.group(1)
                od[reg][first]['Hive'] = hive
                desc = result.group(2)
                od[reg][first]['Description'] = desc
    
            elif date.match(data):
                result = date.match(data)
                hive = result.group(1)
                od[reg][first]['Hive'] = hive
                time = result.group(2)
                od[reg][first]['Timestamp'] = time
    
            else:
                od[reg][first]['Finding'] = data
    
        except IndexError:
             print('error w/pattern match')
    
    run_rip()
    pprint.pprint(od)
    

Sample Input:

    
    
    bitbucket_user v.20091020
    (NTUSER.DAT) TEST - Get user BitBucket values
    
    Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket
    LastWrite Time Sat Nov 28 03:06:35 2015 (UTC)
    
    Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket\Volume
    LastWrite Time = Sat Nov 28 16:00:16 2015 (UTC)
    


Answer: If I understand your question correctly, you want to change the lines where
you're actually adding values to your dictionary (e.g. the
`od[reg][first]['Hive'] = hive` line and the similar one for `desc` and
`time`) to create a list for each `reg` and `first` value and then extend that
list with each item being added. Your dictionary subclass takes care of
creating the nested dictionaries for you, but it won't build a list at the
end.

I think the best way to do this is to use the `setdefault` method on the inner
dictionary:

    
    
    od[reg][first].setdefault("Hive", []).append(hive)
    

The `setdefault` will add the second value (the "default", here an empty list)
to the dictionary if the first argument doesn't exist as a key. It preempts
the dictionary's `__missing__` method creating the item, which is good, since
we want a the value to be list rather than another layer of dictionary. The
method returns the value for the key in all cases (whether it added a new
value or if there was one already), so we can chain it with `append` to add
our new `hive` value to the list.

