Instantiate FamilyOption in Python

Dear Revit API Experts,

I have been using successfully the following IronPython2 code to instantiate FamilyLoaderOptionsHandler class on Revit 2019 and 2022:

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):

	def OnFamilyFound(self, familyInUse, overwriteParameterValues):
		overwriteParameterValues.Value = True
		return True
	
	def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
		source.Value = DB.FamilySource.Family
		overwriteParameterValues.Value = True
		return True

familyLoaderOpts = FamilyLoaderOptionsHandler()

These days I tried running the upper code on Revit 2024 with default Python engine (CPython3), and an error is raised on the last line:

interface takes exactly one argument

Does anyone know how to instantiate the upper FamilyLoaderOptionsHandler class on Revit 2024/2025 with CPython3 engine?
Is this some kind of bug with PythonNET 2.5 class inheritance?

I would be grateful for any kind of help. Thank you in advance for any kind of help.

This is a known issue with subclassing in older versions of PythonNet
You could either use IronPython2 or IronPython3
If you are on Revit 2025.4 you can use PythonNet3 Engine
Finally you can use a random namespace for the class

import uuid

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):

    __namespace__ = str(uuid.uuid4)

	def OnFamilyFound(self, familyInUse, overwriteParameterValues):
    ...
1 Like

Hi @Mike.Buttery ,
Thank you very much for the help and explanation.
I am sadly stuck with default version of PythonNET, until it is replaced with a new one. My IT needs to approve anything, which is not shipped by default to Dynamo. It’s a huge headache.

I tried your code on Revit 2024.3, with default CPython3 engine (I assume this is pythonNET 2.5?):

import uuid

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):
	
	__namespace__ = str(uuid.uuid4)
	
	def OnFamilyFound(self, familyInUse, overwriteParameterValues):
		overwriteParameterValues.Value = True
		return True
	
	def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
		source.Value = DB.FamilySource.Family
		overwriteParameterValues.Value = True
		return True


familyLoaderOpts = FamilyLoaderOptionsHandler()

The last line raises an error:

No constructor matches given arguments: ()

Do you have any suggestion what am I doing wrong?

@george def __init__(self): u want to look into constructors in class definition.

1 Like

Thank you @BimAmbit ,

So your suggestion is to add __namespace__ = str(uuid.uuid4) inside def __init__(self)::

import uuid

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):

	def __init__(self):
		__namespace__ = str(uuid.uuid4)
	
	def OnFamilyFound(self, familyInUse, overwriteParameterValues):
		overwriteParameterValues.Value = True
		return True
	
	def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
		source.Value = DB.FamilySource.Family
		overwriteParameterValues.Value = True
		return True


familyLoaderOpts = FamilyLoaderOptionsHandler()

In that case, the last line raises an error:

interface takes exactly one argument

__namespace__ goes before init()

What’s rdb?, perhaps try DB.FamilySource.Family

It’s a bit tough without seeing all the code context because we don’t know how your imports are set up

1 Like

Hi @Mike.Buttery ,
My mistake. rdb is DB. I apologize for this. I corrected it in the all of the code above.
I am just trying to Load a family. The rest of the code works. The issue starts with familyLoaderOpts = FamilyLoaderOptionsHandler() line.

1 Like

CPython3 (PythonNet2.5) do not ability to override .NET methods interface that have out or ref in Python (example by returning the modified parameter values in a tuple like PythonNet3).

For Revit 2024 and lower use IronPython in this case,
furthermore in Dymano2.19 (Revit 2024) CPython3 has some additional bugs, probably due to targeting the NetStandard 2.0 Framework with PythonNet2.5 in a Framework 4.8 environment.

1 Like

not quite, i’d keep __namespace__ = str(uuid.uuid4) executed when the class is defined. btw are u trying to generate a unique namespace every run? isn’t it str(uuid.uuid4()) instead?

1 Like

yes, my bad

1 Like

Why create an object, just construct it in the method
familyDocument.LoadFamily(doc, FamilyLoaderOptionsHandler())

1 Like

hm.. the error can be suppressed. but whether the interface is actually usable is another matter.
(cpython3 engine)

1 Like

Hi @c.poupin ,
Thank you very much for the explanation.
So definitely it is not possible to instantiate upper FamilyLoaderOptionsHandler class with Revit 2024.3, and default python CPython3 engine (pythonNET 2.5)?

@BimAmbit
Thank you as well for the example code. On my Revit 2024.3, it still raises an error on the last line of your code: No constructor matches given arguments: ().
Would you be able to attach the .dyn file, so that I make sure that I am not doing something wrong? Thank you for this .dyn file in advance.

Thank you @Mike.Buttery
It still raises an error on that line. There is no difference between:
familyLoaderOpts = FamilyLoaderOptionsHandler()
and:
familyDocument.LoadFamily(doc, FamilyLoaderOptionsHandler())

you can’t override parameter values when reloading a family with PythonNet2.5 and it might crash.

I wrote an article about Net. Interface (use the widget translator)

2 Likes

nothing fancy, throw them in a python node. but tbh i don’t see OnFamilyFound being called when i call doc.LoadFamily. best to spend some time on poupin’s article.

import uuid

class FamilyLoaderOptionsHandler(IFamilyLoadOptions):
    __namespace__ = str(uuid.uuid4())
    
    def __init__(self):
         pass
    
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
        overwriteParameterValues.Value = True
        return True
    
    def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
        source.Value = rdb.FamilySource.Family
        overwriteParameterValues.Value = True
        return True
     
familyLoaderOpts = FamilyLoaderOptionsHandler()

doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

OUT = type(familyLoaderOpts).__name__, FamilyLoaderOptionsHandler.__namespace__
1 Like

Thank you very much @c.poupin
I will read that article, just at the glance of it - it provides a lot of useful information.

So which Python package would you recommend me to use on Revit 2024.3?
DynamoIronPython2.7, DynamoIronPython3, PythonNET3?


Thank you @BimAmbit. Indeed on line:

On my Revit 2024.3, I get an error: No constructor matches given arguments: ().
Nevertheless, thank you for your time and help.

1 Like

DynamoIronPython2.7 or DynamoIronPython3

PythonNET3 is only available for Dynamo 3.x

1 Like

Understood. I will the try to make an argument with our IT, to allow installation of DynamoIronPython2.7. Thank you @c.poupin .

And also @Mike.Buttery and @BimAmbit as well for your time and help.

3 Likes

Alternatively you can look into building a zero touch node to do this work (no more or less secure than you writing your own Python and executing that), or leverage another means of transferring the content into the file or avoid the need (would have to have context on why you’re doing this to help with those options though).

1 Like

Thank you for the suggestions @jacob.small .
Making a ‘Zero touch node’, would require writing it in C#?
i am not sure I can do this. If anyone could write such custom node for FamilyLoaderOptions, it would be of huge help.