-1

I'm attempting to use python and boto to print a list of instances and IPs from Amazon EC2.

I'm used to PHP's nice multidimensional arrays and the similar JSON syntax but I'm having a lot of trouble in python. I tried using AutoVivification as mentioned in What's the best way to initialize a dict of dicts in Python? but am not having luck with access objects in it.

Here is my code:

import sys
import os
import boto
import string
import urllib2
from pprint import pprint
from inspect import getmembers
from datetime import datetime

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

conn = boto.connect_ec2_endpoint(ec2_url, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
tags = conn.get_all_tags()
myInstances = AutoVivification()

for tag in tags:
    if ( tag.res_type == 'instance' and tag.name == 'Name'):
        if( tag.res_id ):
            myInstances[tag.res_id]['myid'] = tag.res_id
            myInstances[tag.res_id]['name'] = tag.value

addrs = conn.get_all_addresses()
for a in addrs:
    if( a.instance_id ):
      myInstances[a.instance_id]['ip'] = a.public_ip

pprint( myInstances )

for i in myInstances:
    print i.name.rjust(25), i.myid

If I do pprint( myInstances ) then I am able to see the multidimensional dict that I have created, but i am not able to access the sub-arrays with i.myid - I get errors like:

AttributeError: 'unicode' object has no attribute 'myid'
AttributeError: 'unicode' object has no attribute 'name'

Doing pprint( myInstances) gives me something like:

{u'i-08148364': {'myid': u'i-18243322', 'name': u'nagios', 'ip': u'1.2.3.4'}}

so I don't understand why I can't access these items.

Community
  • 1
  • 1
cwd
  • 53,018
  • 53
  • 161
  • 198

1 Answers1

3

Your problem is just in how you're trying to access the items:

for i in myInstances:
    # i iterates over the KEYS in myInstances
    print i.name.rjust(25), i.myid

This attempts, for each key in myInstances, to print i.name.rjust(25) and so on. What you want is to access the value of the given keys (and to use the right Python syntax for accessing dictionary elements):

for i in myInstances:
    # i iterates over the KEYS in myInstances
    print myInstances[i]["name"].rjust(25), myInstances[i]["myid"]

Or if you don't need the keys at all, just iterate over the values in the first place:

for i in myInstances.values():
    # i iterates over the VALUES in myInstances
    print i["name"].rjust(25), i["myid"]

Or finally, per request, if you really want to iterate over keys and values at once:

for k, v in myInstances.iteritems():
    print k, v["name"].rjust(25), v["myid"]
Henry Keiter
  • 16,863
  • 7
  • 51
  • 80