Python Forum
TypeError: list indices must be integers or slices, not dict
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
TypeError: list indices must be integers or slices, not dict
#1
I am trying to get a list of AWS instances using Boto3.

The user enters the instance IDs, then the script should print out info about the instance. Then it should terminate the instance.

But I am getting this error:
Error:
python3 .\aws_ec2_terminate_instances.py Enter an instance ID separated by commas: i-07c21656a79b8eb45 Deleting Instance IDs: i-07c21656a79b8eb45 Traceback (most recent call last): File ".\aws_ec2_terminate_instances.py", line 15, in <module> instance['Tags'][{'Key': 'Name', 'Value': instance_id}] TypeError: list indices must be integers or slices, not dict
Here is the current state of my code:

import sys
import boto3
import collections
from collections import defaultdict

ec2 = boto3.client('ec2')
instance_id_list = input("Enter an instance ID separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
    print(instance_id)
    instance = ec2.describe_instances(
        InstanceIds=[instance_id]
    ) ['Reservations'][0]['Instances'][0]
    instance['Tags'][{'Key': 'Name', 'Value': instance_id}]
    ec2info = defaultdict()
    for tag in instance.tags:
        if 'Name'in tag['Key']:
            print(tag['Key'])
            name = tag['Value']
    # Add instance info to a dictionary
    print(instance.get('Instances'))
    ec2info[instance.id] = {
        'Instance ID': instance.id,
        'Type': instance.instance_type,
        'State': instance.state['Name'],
        'Private IP': instance.private_ip_address,
        'Public IP': instance.public_ip_address,
        'Launch Time': instance.launch_time
        }
    

attributes = ['Instance ID', 'Type',
              'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
    for key in attributes:
        print("{0}: {1}".format(key, instance[key]))
        print(instance.terminate())
        print("------")
        ec2.instances.filter(InstanceIds=instance).stop()
        ec2.instances.filter(InstanceIds=instance).terminate()
How can I solve this error?
Reply
#2
instance['Tags'] is a list. Index a list using index values (integers). You're getting an error because, instead of an index, you're trying to use a dict: {'Key': 'Name', 'Value': instance_id}.

I'd suggest looking at the return value, because it appears that it isn't what you think it is.
Reply
#3
(Feb-27-2019, 10:26 PM)nilamo Wrote: instance['Tags'] is a list. Index a list using index values (integers). You're getting an error because, instead of an index, you're trying to use a dict: {'Key': 'Name', 'Value': instance_id}.

I'd suggest looking at the return value, because it appears that it isn't what you think it is.

I tried printing out the value of instance in the code, and I got back info about the instance in json format. How do I traverse the json to get at the Name tag?
Quote:{'AmiLaunchIndex': 0, 'ImageId': 'ami-035be7bafff33b6b6', 'InstanceId': 'i-0e3dfaeaa89c7e401', 'InstanceType': 't2.micro', 'KeyName': 'agility-company-nonprod', 'LaunchTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'Monitoring': {'State': 'disabled'}, 'Placement': {'AvailabilityZone': 'us-east-1c', 'GroupName': '', 'Tenancy': 'default'}, 'PrivateDnsName': 'ip-10-48-129-108.us.kworld.kpmg.com', 'PrivateIpAddress': '10.48.129.108', 'ProductCodes': [], 'PublicDnsName': '', 'State': {'Code': 16, 'Name': 'running'}, 'StateTransitionReason': '', 'SubnetId': 'subnet-9fca57e9', 'VpcId': 'vpc-d4ad21b0', 'Architecture': 'x86_64', 'BlockDeviceMappings': [{'DeviceName': '/dev/xvda', 'Ebs': {'AttachTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'DeleteOnTermination': True, 'Status': 'attached', 'VolumeId': 'vol-0943014108b20137a'}}], 'ClientToken': '', 'EbsOptimized': False, 'EnaSupport': True, 'Hypervisor': 'xen', 'NetworkInterfaces': [{'Attachment': {'AttachTime': datetime.datetime(2019, 2, 27, 21, 43, 36, tzinfo=tzutc()), 'AttachmentId': 'eni-attach-054a1daee0609f80e', 'DeleteOnTermination': True, 'DeviceIndex': 0, 'Status': 'attached'}, 'Description': 'Primary network interface', 'Groups': [{'GroupName': 'launch-wizard-29', 'GroupId': 'sg-0ec43fd09c1a4b5fa'}], 'Ipv6Addresses': [], 'MacAddress': '0a:dd:5b:27:5f:70', 'NetworkInterfaceId': 'eni-00904468cbeb24c28', 'OwnerId': '832839043616', 'PrivateIpAddress': '10.48.129.108', 'PrivateIpAddresses': [{'Primary': True, 'PrivateIpAddress': '10.48.129.108'}], 'SourceDestCheck': True, 'Status': 'in-use', 'SubnetId': 'subnet-9fca57e9', 'VpcId': 'vpc-d4ad21b0'}], 'RootDeviceName': '/dev/xvda', 'RootDeviceType': 'ebs', 'SecurityGroups': [{'GroupName': 'launch-wizard-29', 'GroupId': 'sg-0ec43fd09c1a4b5fa'}], 'SourceDestCheck': True, 'Tags': [{'Key': 'Creator', 'Value': 'tdunphy'}, {'Key': 'Name', 'Value': 'test'}, {'Key': 'PrincipalId', 'Value': 'AIDAIZC35XEFCDGBM47UK'}], 'VirtualizationType': 'hvm', 'CpuOptions': {'CoreCount': 1, 'ThreadsPerCore': 1}, 'CapacityReservationSpecification': {'CapacityReservationPreference': 'open'}, 'HibernationOptions': {'Configured': False}}

In the above json the Name tag is almost at the end:
{'Key': 'Name', 'Value': 'test'}
Reply
#4
It looks like you already do, two lines later.

But since you don't know what index you need, you'd iterate over the list. Something like:
tags = instance['Tags']
name = ""
for tag in tags:
    if tag["Key"] == "Name":
        name = tag["Value"]
print(name)
But since you aren't using it's name for anything, you can probably just delete the line instead of fixing it.
Reply
#5
(Feb-27-2019, 10:52 PM)nilamo Wrote: It looks like you already do, two lines later.

But since you don't know what index you need, you'd iterate over the list. Something like:
tags = instance['Tags']
name = ""
for tag in tags:
    if tag["Key"] == "Name":
        name = tag["Value"]
print(name)
But since you aren't using it's name for anything, you can probably just delete the line instead of fixing it.

Ok thanks! That works and I am now able to access the 'Name' tag from the code, and print it out.

I'm getting a new error now when I try to access info about the instance ID from a dictionary. This is how my script outputs now:

Error:
Enter instance IDs separated by commas: i-076361b30ee404bb4 Deleting Instance IDs: i-076361b30ee404bb4 Name: test1 Traceback (most recent call last): File ".\aws_ec2_terminate_instances.py", line 24, in <module> 'Instance ID': instance.id, AttributeError: 'dict' object has no attribute 'id'
This is my current script:

import boto3
import collections
from collections import defaultdict

ec2 = boto3.client('ec2')
instance_id_list = input("Enter instance IDs separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
    print(instance_id)
    instance = ec2.describe_instances(
        InstanceIds=[instance_id]
        )['Reservations'][0]['Instances'][0]
    tags = instance['Tags']
    name = ""
    for tag in tags:
        if tag["Key"] == "Name":
            name = tag["Value"]
    print("Name: ", name)
    # Add instance info to a dictionary
    ec2info = defaultdict()
    ec2info[instance.id] = {
        'Name': name,
        'Instance ID': instance.id,
        'Type': instance.instance_type,
        'State': instance.state['Name'],
        'Private IP': instance.private_ip_address,
        'Public IP': instance.public_ip_address,
        'Launch Time': instance.launch_time
        }
attributes = ['Name', 'Instance ID', 'Type',
              'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
    for key in attributes:
        print("{0}: {1}".format(key, instance[key]))
        print("------")
        print("Terminating the instance:")
        ec2.instances.filter(InstanceIds=instance).stop()
        ec2.instances.filter(InstanceIds=instance).terminate()
I'd appreciate some help on that error!
Reply
#6
Hi all,

I have a script that I wrote that asks a user to enter a list of instance IDs from AWS. The script then prints out info on that server, and terminates it.

When I run the script I get this error:

Error:
Traceback (most recent call last): File ".\aws_ec2_terminate_instances.py", line 23, in <module> 'Instance ID': instance.id, AttributeError: 'dict' object has no attribute 'id'
This is my code:
import boto3
import collections
from collections import defaultdict

ec2 = boto3.client('ec2')
instance_id_list = input("Enter instance IDs separated by commas: ")
instance_ids = instance_id_list.split(",")
print("Deleting Instance IDs:")
for instance_id in instance_ids:
    print(instance_id)
    instance = ec2.describe_instances(
        InstanceIds=[instance_id]
        )['Reservations'][0]['Instances'][0]
    tags = instance['Tags']
    name = ""
    for tag in tags:
        if tag["Key"] == "Name":
            name = tag["Value"]
    # Add instance info to a dictionary
    ec2info = defaultdict()
    ec2info[instance.id] = {
        'Name': name,
        'Instance ID': instance.id,
        'Type': instance.instance_type,
        'State': instance.state['Name'],
        'Private IP': instance.private_ip_address,
        'Public IP': instance.public_ip_address,
        'Launch Time': instance.launch_time
        }
attributes = ['Name', 'Instance ID', 'Type',
              'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
    for key in attributes:
        print("{0}: {1}".format(key, instance[key]))
        print("------")
        print("Terminating the instance:")
        ec2.instances.filter(InstanceIds=instance).stop()
        ec2.instances.filter(InstanceIds=instance).terminate()
I seem to be getting a dictionary error when I print out the instance.id.

This script is based on another script that pulls a list of all AWS instances in an account, and prints out their info. That one works!
from collections import defaultdict

import boto3

"""
A tool for retrieving basic information from the running EC2 instances.
"""

# Connect to EC2
ec2 = boto3.resource('ec2')

# Get information for all running instances
running_instances = ec2.instances.filter(Filters=[{
    'Name': 'instance-state-name',
    'Values': ['running']}])

ec2info = defaultdict()
for instance in running_instances:
    for tag in instance.tags:
        if 'Name'in tag['Key']:
            print(tag['Key'])
            name = tag['Value']
    # Add instance info to a dictionary         
    ec2info[instance.id] = {
        'Name': name,
        'Instance ID': instance.id,
        'Type': instance.instance_type,
        'State': instance.state['Name'],
        'Private IP': instance.private_ip_address,
        'Public IP': instance.public_ip_address,
        'Launch Time': instance.launch_time
        }

attributes = ['Name', 'Instance ID', 'Type', 'State', 'Private IP', 'Public IP', 'Launch Time']
for instance_id, instance in ec2info.items():
    for key in attributes:
        print("{0}: {1}".format(key, instance[key]))
    print("------")
Here is a sample of the output from the working script above:

Name: test1
Instance ID: i-076361b30ee404bb4
Type: t2.micro
State: running
Private IP: 10.48.129.89
Public IP: None
Launch Time: 2019-02-27 22:45:56+00:00
------
Name: USAWSCDLX00061
Instance ID: i-0463897140af217f8
Type: m4.large
State: running
Private IP: 10.48.136.41
Public IP: None
Launch Time: 2017-12-20 14:26:30+00:00
What I'm unclear on is why I can print the instance.id from the dictionary in the second program, and it gives the error: 'dict' object has no attribute 'id' on the first script I show.

How can I solve this error?
Reply
#7
When in doubt, print() it out!

What's an instance?

Also, there's no reason to double post. This place isn't that big lol.
Reply
#8
(Feb-28-2019, 08:14 PM)nilamo Wrote: When in doubt, print() it out! What's an instance? Also, there's no reason to double post. This place isn't that big lol.

Haha! Ok man. Sorry about that. I've actually made some progress since I posted this.

This is the value of the instance variable: AWS EC2 JSON
It's your typical aws json output that you might be familiar with.

If I format the dictionary like this:

ec2info = defaultdict()
    ec2info[instance['InstanceId']] = {
        'Name': name,
        'Instance ID': instance['InstanceId'],
        'Type': instance['InstanceType'],
        'State': instance['State'],
        'Private IP': instance['PrivateIpAddress'],
        'Launch Time': instance['LaunchTime']
        }
I can run my print statements:
attributes = ['Name', 'Instance ID', 'Type',
              'State', 'Private IP', 'Launch Time']
print("------")
for instance_id, instance in ec2info.items():
    for key in attributes:
        print("{0}: {1}".format(key, instance[key]))
    print("------")
And it works!

------
Name: USAWSCDLX00061
Instance ID: i-0463897140af217f8
Type: m4.large
State: {'Code': 16, 'Name': 'running'}
Private IP: 10.48.136.41
Launch Time: 2017-12-20 14:26:30+00:00
------
I have a couple of questions tho, I was hoping you could help me with.

For the list instance script that I created: aws_ec2_list_instance_info.py

why am I able to format the dictionary like this, and have it print out the information:

    ec2info[instance.id] = {
        'Name': name,
        'Instance ID': instance.id,
        'Type': instance.instance_type,
        'State': instance.state['Name'],
        'Private IP': instance.private_ip_address,
        'Public IP': instance.public_ip_address,
        'Launch Time': instance.launch_time
        }
But in my terminate script (aws_ec2_terminate_instances.py, I have to access the dictionary info like this:

ec2info = defaultdict()
    ec2info[instance['InstanceId']] = {
        'Name': name,
        'Instance ID': instance['InstanceId'],
        'Type': instance['InstanceType'],
        'State': instance['State'],
        'Private IP': instance['PrivateIpAddress'],
        'Launch Time': instance['LaunchTime']
        }
I'd appreciate it if you could explain the difference!

Also all my attempts to access the state information failed.

If I access it as 'State': instance['State'], I get 'State': {'Code': 16, 'Name': 'running'}

But if I try to access it as: 'State': instance['State.Name'],

I get this error: KeyError: 'State.Name'

I just want to get at the running state. If you could help with that too, I would appreciate it!
Reply
#9
Those scripts have different values for what's called instance. In one, it's whatever's returned by describe_instances()
instance = ec2.describe_instances(
        InstanceIds=[instance_id]
        )['Reservations'][0]['Instances'][0]
...but the other one looks like some sort of custom object:
running_instances = ec2.instances.filter(Filters=[{
    'Name': 'instance-state-name',
    'Values': ['running']}])
The describe_instances() probably returns a dict of key-value strings, while the other one probably has extra functionality. You have to get info about them differently, because they're different things (only one is a dict).
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  tuple indices must be integers or slices, not str cybertooth 16 11,465 Nov-02-2023, 01:20 PM
Last Post: brewer32
  No matter what I do I get back "List indices must be integers or slices, not list" Radical 4 1,161 Sep-24-2023, 05:03 AM
Last Post: deanhystad
  boto3 - Error - TypeError: string indices must be integers kpatil 7 1,232 Jun-09-2023, 06:56 PM
Last Post: kpatil
  Why do I have to repeat items in list slices in order to make this work? Pythonica 7 1,322 May-22-2023, 10:39 PM
Last Post: ICanIBB
  Response.json list indices must be integers or slices, not str [SOLVED] AlphaInc 4 6,370 Mar-24-2023, 08:34 AM
Last Post: fullytotal
Question How to append integers from file to list? Milan 8 1,447 Mar-11-2023, 10:59 PM
Last Post: DeaD_EyE
  "TypeError: string indices must be integers, not 'str'" while not using any indices bul1t 2 2,014 Feb-11-2023, 07:03 PM
Last Post: deanhystad
  Error "list indices must be integers or slices, not str" dee 2 1,455 Dec-30-2022, 05:38 PM
Last Post: dee
  TypeError: string indices must be integers JonWayn 12 3,383 Aug-31-2022, 03:29 PM
Last Post: deanhystad
  read a text file, find all integers, append to list oldtrafford 12 3,521 Aug-11-2022, 08:23 AM
Last Post: Pedroski55

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020