Python script for bulk models

Hi everyone, I am trying write a script that to extract data from bulk revit files.
What I am expect to do is open one revit file->get data (warnings and groups) from the file-> close file->open another one revit file and do the same.
However, I get an error from my script as shown below image and code. If I only extract warnings, the script is smooth without error, but when I try to extract group list as well. The error appear.
Can anyone help me to solve the problem? Thank you!

Code:

import clr, System

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference('System')
from System.Collections.Generic import List

# Open and save Options
openoption = OpenOptions()
openoption.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets


# Current Document
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

 
# Preparing Input
docpaths = IN[0] if isinstance(IN[0], list) else [IN[0]]


# Variables
warning_list = []
group_list = []

# Function
def get_element_class(ofclass):
	i = FilteredElementCollector(doc).OfClass(ofclass).WhereElementIsNotElementType().ToElements()
	return i

# Core Data Processing
for document in docpaths:
	modelpath = FilePath(document)
	doc = app.OpenDocumentFile(modelpath, openoption)

	# Warnings
	warnings = doc.GetWarnings()
	for warning in warnings:
		warning_list.append(warning.GetDescriptionText())

	# Group
	groups = get_element_class(Group)
	group_list.append(groups)
	doc.Close(False)


OUT = warning_list, group_list

I think the reference to doc is confusing. In the get_element_class function, doc has a global scope for the document open in the interface, while within the for loop it is being changed with every filepath, so the original doc is no longer valid for get_element_class. You should make doc an input argument for that function:

def get_element_class(ofclass, document):
	i = FilteredElementCollector(document).OfClass(ofclass).WhereElementIsNotElementType().ToElements()
	return i

and invoke it like this:
get_element_class(Group, doc)

or to avoid any confusion, build the FilteredElementCollector inside the for loop, without a function.

Referring to what Jeremy Tammik said, Revit is not mean to bulk process files. You should use forge for this kind of operations, especially when you have a large amount of files to process

  1. Forge is not feasible for everyone from the standpoint of resources, app permissions, etc.
  2. This task is totally feasible and relatively easy in Dynamo (unless Revit files of different versions are targeted).

A few years ago I tried multiple ways to do something similar.

The batch processor seemed the only way for me to get something like this to work.

1 Like

It works now! Thanks for your help!

This seems very good tool for my task!
I am very interested to try this. Is it work based on python and dynamo script?

It is is pretty well documented. Works with py and dyn files. (some need just a little adjustment) And it catches some problems that might occur while batch processing multiple Revit files.