Ideally, I could choose to either fail silently or just instead display my own message box that is tailored to our use case.
The way to disable the pyRevit exception window is exactly what you describe above, which is to say:
Catch the exception.
Then, you can specify whether to fail silently or display your own message. It seems like you are expecting to have this option without taking the step of catching each exception, but there is no way to display a message box tailored to your use case if you don’t know what use case caused the exception.
I don’t blame you at all for wanting to fail silently, although, I would say it is better to fail quietly rather than silently. This is what I do: Nearly every step of my script/function is preceded by a check like shown in this pseudocode:
def my_function():
if some_variable != what_i_expect:
log('ERROR: some_variable was not as expected')
else:
second_step = do_next_step(some_variable)
if second_step > expected_maximum_value:
log('WARNING: second_step did not succeed for element {}'.format(element.Name))
else:
try:
result = operation_that_may_fail(second_step)
except:
log('ERROR: operation failed on element {}'.format(element.Name))
else:
log('INFO: operation suceeded for element {}!'.format(element.Name))
return result
So you see, when something fails, the typical result is that nothing happens. Yet, you are not left in the dark about it because every possible failure gets logged by whatever logging mechanism you choose to employ. During testing and debugging, you enable the log. Then, when you are ready to deploy, disable it so your users don’t need to sit there watching something print out.
It sounds like a lot of work to write all these checks and error messages, but if you write them into your code from the start, it saves you so much time trying to nail down bugs. It becomes easy to know what’s happening at every major operation. The checks prevent most exceptions from happening, in the process notifying you that a particular element didn’t pass.
For logging, you could use pyRevit’s logger, but that tends to print a HUGE amount of info related to the inner workings of pyRevit, which is irrelevant for your purposes. You could use python’s logging module. I have tried it, but it seems like overkill to me and is a bit complex to set up, so I went with my own toggleable print function like so:
GLOBAL_DEBUG = True
# Toggleable print function. Turn on to debug.
def p(*to_print):
if GLOBAL_DEBUG:
for item in to_print:
print item
if 2 + 2 == 4:
p('All is well.')
else:
p('The universe is f*****!', 'Abandon all hope!')
Here is an example function:
def show_element(input_object):
if isinstance(input_object, ListItem):
element = input_object.elem
list_item = input_object
elif isinstance(input_object, Element):
element = input_object
else: p('ERROR: input_object was unsupported type in show_element')
if not element: p('element was None') # do lots of checks like this to make sure you are not passing in a null argument.
else:
global uidoc
# Acquire tag's OwnerView and open it before ShowElements() to avoid pop-up dialog
active_view = uidoc.ActiveView
try: owner_view_id = element.OwnerViewId
except: p('ERROR: Element is not valid, possibly deleted.')
else:
# If element's OwnerView is not already open, open it to avoid popup dialog, then show element.
if active_view.Id != owner_view_id:
owner_view = doc.GetElement(owner_view_id)
uidoc.ActiveView = owner_view
# Check if element is visible in view before showing, to prevent UI unresponsiveness due to popup dialog.
if not list_item.is_visible_in_view:
message = 'WARNING: Tag is not visible in view. Cannot show_element.'
p(message)
else:
# Show the element
uidoc.ShowElements(element)
After a small amount of testing, you will discover the likely exceptions and come up with a way of handling them. Any remaining exceptions (which will be few and far between) will be brought to your attention when your users see the ugly red exception window. This is a good thing. It will enable you to check the log and fix the issue for good.
I think the system I described should accomplish your goals. It fails safely. It fails quietly, but if you listen closely, you can still hear what went wrong.