I've written this script that helped me a lot with my last project. As a new blender user it's too easy for me to bloat my projects w/o knowing where the bloat is. This inspector lists out my project so it is more knowable. To use this script in Blender 3.0 you will have to follow the instructions here Blender 3.0.1 How to import 'tabulate' into script
to pip3 install the tabulate import.
import bpy,os
from bpy import context
from tabulate import tabulate
import operator
import sys
import numbers
import os
print("PYTHONPATH:", os.environ.get('PYTHONPATH'))
print("PATH:", os.environ.get('PATH'))
#
# Sorts a table based on a col tuple
#
def sort_table(table, cols):
""" sort a table by multiple columns
table: a list of lists (or tuple of tuples) where each inner list
represents a row
cols: a list (or tuple) specifying the column numbers to sort by
e.g. (1,0) would sort by column 1, then by column 0
"""
for col in reversed(cols):
table = sorted(table, key=operator.itemgetter(col))
return table
#
# Takes a table and for all numbers in the table
# formats them with commas and returns a new table
#
def insertCommas(table):
newTable = []
for row in table:
resultsRow = []
for col in row:
if isinstance( col, numbers.Number):
newCol = '{:,}'.format(col)
else:
newCol = col
resultsRow.append(newCol)
newTable.append( resultsRow)
return newTable
#
# Prints a table and summary of all project meshes, including total and unique total (dups vs linked)
#
iTotalVerts = 0
iTotalUniqueVerts = 0
iTotalEdges = 0
iTotalUniqueEdges = 0
iTotalFaces = 0
iTotalUniqueFaces = 0
resultsTable = []
totalObjects = 0
totalDups = 0
#
# First build a table of all items and their names/addresses
# so that we can understand when we have a 'linked' object
#
name_dict = {}
address_dict = {}
for o in context.scene.objects:
if o.type != 'MESH':
continue
name_dict[o.name] = o.data.as_pointer()
address_dict[o.data.as_pointer()] = o.name
#print("name_dict " + str(name_dict))
#print("\n")
#
# Now build the list of objects and sizes and look up dup counts
#
for o in context.scene.objects:
if o.type != 'MESH':
continue
name_dict[o.name] = o.data.as_pointer()
obj_mesh = o.data
resultsRow = []
me = o.data
verts = len(me.vertices)
edges = len(me.edges)
faces = len(me.polygons)
iTotalVerts += verts
iTotalEdges += edges
iTotalFaces += faces
resultsRow.append(o.name)
resultsRow.append(verts)
resultsRow.append(edges)
resultsRow.append(faces)
address = o.data.as_pointer()
dupCount = 0
address = name_dict[ o.name ]
for each in name_dict:
#print( "Looking for address " + str(address) + " comparing with " + str(name_dict[each]))
if address == name_dict[each]:
dupCount = dupCount + 1
resultsRow.append(dupCount)
if dupCount > 1:
resultsRow.append(str(o.data.as_pointer()))
totalDups = totalDups + 1
else:
resultsRow.append("")
iTotalUniqueVerts += verts
iTotalUniqueEdges += edges
iTotalUniqueFaces += faces
resultsTable.append(resultsRow)
totalObjects = totalObjects +1
print("address_dicts = " + str(address_dict))
sortedResultsTable = sort_table( resultsTable, (1,0))
formattedAndSortedTable = insertCommas( sortedResultsTable )
headers = ["Name", "Verts", "Edges", "Faces", "Link Count", "Linked to"]
print(tabulate(formattedAndSortedTable, headers=headers, stralign="right"))
strTotalObjects = '{:,}'.format(totalObjects)
strTotalDups = '{:,}'.format(totalDups)
strTotalVerts = '{:,}'.format( iTotalVerts)
strTotalEdges = '{:,}'.format( iTotalEdges)
strTotalFaces = '{:,}'.format( iTotalFaces)
strTotalVertsUnique = '{:,}'.format(iTotalUniqueVerts)
strTotalEdgesUnique = '{:,}'.format(iTotalUniqueEdges)
strTotalFacesUnique = '{:,}'.format(iTotalUniqueFaces)
summaryOutput = "\nSummary: Objects: " + strTotalObjects + "/" + strTotalDups + ", Unique: " + '{:,}'.format(len(address_dict)) + ", Verts: " + strTotalVerts + "/" + strTotalVertsUnique + ", Edges: " + strTotalEdges + "/" + strTotalEdgesUnique + ", Faces: " + strTotalFaces + "/" +strTotalFacesUnique
print( summaryOutput)
print( "\nNote: Total/Unique, Totals include all linked objects, Unique only counts unique objects")
Here is a sample of the output, nicely tabulated, a list of all Meshes and their vert/edge/face sizes as well as a 'linked' count and the memory address (for recognizing dup objects). The summary shows the totals for both all objects and just unique objects. This information makes it easy for me to find large objects and/or objects that are better served as dups. I see no way in the Blender UI to know if a particular object is a duplicate or a linked object. This gives me that visibility too! :-)
ENJOY!

And Updated output
-------------------------------------- ------- ------- ------- ------------ -----------
FogPlane 4 4 1 1
FogPlane.001 4 4 1 1
flying-sparrow-silhouette-25-424287647 4 4 1 1
lonemountain_sky 4 4 1 1
iceberg3 7 12 7 1
iceberg8 7 12 7 1
iceberg1 8 18 12 1
iceberg2 8 15 9 1
iceberg4 8 12 6 1
iceberg5 8 15 9 1
iceberg6 8 15 9 1
iceberg7 8 18 12 1
iceberg9 8 12 6 1
rock 8 18 12 1
iceberg10 10 24 16 1
Landscape.006 10,526 20,815 10,290 1
Landscape.003 13,720 27,158 13,439 1
Landscape.004 13,720 27,158 13,439 1
Landscape 16,384 32,512 16,129 1
Landscape.001 16,384 32,512 16,129 1
Landscape.005 16,384 32,512 16,129 1
Landscape.007 16,384 32,512 16,129 1
IcePlane 17,689 35,112 17,424 1
Ocean 17,689 35,112 17,424 1
Landscape.002 20,535 40,451 19,921 1
tree.004 31,928 55,972 24,044 1
tree.009 36,556 49,198 16,880 1
MainLandscape 42,084 125,428 83,345 1
tree.002 43,372 76,012 32,640 1
leaves.001 47,054 63,219 21,646 1
leaves 57,180 76,934 26,388 1
tree.005 66,940 90,270 31,048 1
tree 71,384 95,904 32,836 1
tree.008 140,382 188,353 64,382 1
tree.001 193,644 359,728 177,948 1
tree.007 204,526 252,671 78,250 1
tree.003 330,782 413,827 126,434 1
tree.006 338,582 423,615 129,438 1
Summary: Objects: 38/0, Unique: 38, Verts: 1,763,933/1,763,933, Edges: 2,587,172/2,587,172, Faces: 1,001,841/1,001,841
Note: Total/Unique, Totals include all linked objects, Unique only counts unique objects
import bpy from bpy import context sumfaces = [] for o in context.scene.objects: if o.type != 'MESH': continue me = o.data verts = len(me.vertices) edges = len(me.edges) faces = len(me.polygons) sumfaces.append(faces) print("%s: verts:%d edges:%d polys %d" % (o.name, verts, edges, faces)) print("total polys %d" % sum(sumfaces))
$\endgroup$