Python: Associating Function Output to Strings, then Combining into Dictionary
Question: I have a list of computer nodes called node_names, and I want to find the
amount of free ram in each node, and store that in a second list. I then want
to combine these lists into a dictionary.

I have:

    
    
    for i in range(0, number_of_nodes):
        sys_output = [commands.getoutput('ssh %s \'free -m\'' % node_names[i])]
        free_memory = [x.split()[9] for x in sys_output]
        print free_memory
    

For 4 nodes, this returns `[mem1],[mem2],[mem3],[mem4]`.

How can I combine each memory value into a single list? I'm having difficulty
assigning `free_memory` as a list instead of a string which is replaced after
each loop iteration.

Once I have a memory list, I should be able to combine it with the node_names
list to make a dictionary file and do any necessary sorting.


Answer: I would recommend just building the dictionary directly:

    
    
    import commands
    
    node_free_mem = {}
    
    for n in node_names:
        sys_output = commands.getoutput("ssh %s 'free -m'" % n)
        free_memory = sys_output.split()[9]
        node_free_mem[n] = int(free_memory)
    

Here's code that does exactly what you asked: it builds a list, then uses the
list to make a dictionary. Discussion after the code.

    
    
    import commands
    
    def get_free_mem(node_name):
        sys_output = commands.getoutput('ssh %s \'free -m\'' % node_name)
        free_memory = sys_output.split()[9]
        return int(free_memory)
    
    free_list = [get_free_mem(n) for n in node_names]
    node_free_mem = dict(zip(node_names, free_list))
    

Note that in both code samples I simply iterate over the list of node names,
rather than using a `range()` to get index numbers and indexing the list. It's
simplest and best in Python to just ask for what you want: you want the names,
so ask for those.

I made a helper function for the code to get free memory. Then a simple list
comprehension builds a parallel list of free memory values.

The only tricky bit is building the dict. This use of `zip()` is actually
pretty common in Python and is discussed here:

[Map two lists into a dictionary in
Python](http://stackoverflow.com/questions/209840/map-two-lists-into-a-
dictionary-in-python)

For large lists in Python 2.x you might want to use `itertools.izip()` instead
of the built-in `zip()`, but in Python 3.x you just use the built-in `zip()`.

EDIT: cleaned up the code; it should work now.

`commands.getoutput()` returns a string. There is no need to package up the
string inside a list, so I removed the square braces. Then in turn there is no
need for a list comprehension to get out the free_memory value; just split the
string. Now we have a simple string that may be passed to `int()` to convert
to integer.

