This script will interrogate the WKT makeup of the geometry and if the geometry has a hole will fill it in. The output is a feature class with filled-in polygons only, only those that had holes in the first place are copied to the new feature class. You can then use Select By Location to find polygons in your original dataset that are completely within the new filled feature class. This has worked for me but I knew my data had no multipolygons, each feature was a single polygon (you could remove multiparts or explode to achieve this), also if a polygon was within another polygon it was an island and it didn't just sit on top of another polygon.
import arcpy
# this is where your dataset resides, change path between ""
arcpy.env.workspace = r"C:\Users\******\Documents\ArcGIS\Default.gdb"
# this is the name of your feature class from the above path
fc = "your_fc"
# grab the WKT values for each feature
# this is a Python dictionary
shape_dict = {}
# for each unique feature we will get the WKT and store in the dictionary
# OBJECTID is a unique id but you can replace this with any unique id field name
with arcpy.da.SearchCursor(fc, ["OBJECTID", "SHAPE@WKT"]) as cursor:
for row in cursor:
shape_dict[row[0]] = row[1]
# this is an empty Python list, we will populate it witt WKT to make new features
feature_list = []
# for each unique feature in the dictionary
for key, value in shape_dict.iteritems():
# get an index list of all open parentheses
po_index = [pos for pos, char in enumerate(value) if char == "("]
# get an index list of all closing parentheses index list
pc_index = [pos for pos, char in enumerate(value) if char == ")"]
# I have found that WKT for polygons seems to always print as
# MULTIPOLYGON (((
# even if a simple polygon. This rebuilds the WKT to remove holes
if len(po_index) > 3:
new_wkt = value[0:pc_index[0]+1] + "))"
new_geom = arcpy.FromWKT(new_wkt)
# and appends the new geom to a list
feature_list.append(new_geom)
# creates a feature class based on the list and call it filled
# this will be put in the same path at the top of the script
arcpy.CopyFeatures_management(feature_list, "filled")
# set this to match the EPSG of the original polygons
# 27700 is for British National Grid, change to suit your projection
arcpy.DefineProjection_management("filled", "27700")