Iterate thru ec2 describe instance boto3

Here's how you could display the information via the AWS Command-Line Interface (CLI):

aws ec2 describe-instances --query 'Reservations[*].Instances[*].[InstanceId, Hypervisor, NetworkInterfaces[0].Attachment.DeleteOnTermination]'

Here's some Python:

import boto3

client = boto3.client('ec2')

response = client.describe_instances()

for r in response['Reservations']:
  for i in r['Instances']:
    print i['InstanceId'], i['Hypervisor']
    for b in i['BlockDeviceMappings']:
      print b['Ebs']['DeleteOnTermination']

I know I am kinda late to the party, but my 2 cents for readability is to use generator comprehension (python 3):

import boto3

client = boto3.client('ec2')

response = client.describe_instances()
block_mappings = (block_mapping
                  for reservation in response["Reservations"]
                  for instance in reservation["Instances"]
                  for block_mapping in instance["BlockDeviceMappings"])

for block_mapping in block_mappings:
  print(block_mapping["Ebs"]["DeleteOnTermination"])

You can also use jmespath, the same query engine behind awscli --query flag, to get the nested results automatically:

import jmespath
import boto3

client = boto3.client('ec2')

response = client.describe_instances()
print(jmespath.search(
    "Reservations[].Instances[].DeviceBlockMappings[].Ebs.DeleteOnTermination", 
    response
))

Or, in case you need more power, use pyjq. Its syntax is a little different from jmespath which is used in awscli, but it has more advantages over it. Let's say you want not only the DeviceBlockMappings but also to keep to which InstanceId it is related to. In jmespath you can't really do this, because there is no access to outer structures, just a single nested path. In pyjq you can do something like this:

import pyjq
import boto3

client = boto3.client('ec2')

response = client.describe_instances()
print(pyjq.all(
  "{id: .Reservations[].Instances[].InstanceId, d:.Reservations[].Instances[].DeviceBlockMappings[]}",
  response
))

This will yield a list of device block mappings with their corresponding InstanceId, kind of like a mongo's unwind operation:

{'id': string, d: {'Ebs': {'DeleteOnTermination': boolean}}}[]

Here's John's answer but updated for Python3

import boto3

client = boto3.client('ec2')

response = client.describe_instances()

for r in response['Reservations']:
    for i in r['Instances']:
        print(i['InstanceId'], i['Hypervisor'])
        for b in i['BlockDeviceMappings']:
            print(b['Ebs']['DeleteOnTermination'])