keipertk
keipertk

Reputation: 27

Python: Associating Function Output to Strings, then Combining into Dictionary

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.

Upvotes: 1

Views: 70

Answers (1)

steveha
steveha

Reputation: 76695

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

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.

Upvotes: 2

Related Questions