Generic Python error handler?

I’m trying to code a generic type of error handler that I can call from the except clauses from different scripts where the error_handler procedure can take different routes depending on what is passed to it.

Ideally, I want a generic error handler that will catch any/all types of errors.
My question is, will the str(e) in the except clause below work correctly for all or most types of errors?

try:

    i = 1 / 0  # divide by zero error

except Exception as e:
    error_handler(str(e))  # will this line str(e) work for all errors?
1 Like

We have tons of error handling where the except clauses look like (see image below) from a UDT Tag Value Change script.

I want to replace this code (code that builds parameters, calls Named Query and logs to the database)

I want to replace it with a single line code like error_handler() (see my original post above) where the error_handler procedure can take different routes depending on what is passed to it.

The error_handler() procedure will be in a script procedure that is in an inheritable/parent project

err_handler

For some reason, the code like getattr(e, 'message', repr(e)) throws me for a bit of a loop, possibly making me think the error handling is more complicated than it really is? My experiments using str(e) seem to work correctly. I think I just need someone else to tell me ha

getattr(e, 'message', repr(e)) is retrieving the property named message from e, and if e does not have a message property, it’s returning repr(e). repr can be distinct from str, but usually won’t be for Java objects, including exceptions. It’s not clear from your snippet if Exception is Python’s built-in Exception type or Java’s; someone may be importing from java.lang import Exception earlier in that script.

I no longer use from java.lang import Exception. I use from java.lang import Throwable instead. Python’s Exception will not catch java exceptions at all. Java’s Throwable will not catch any python exceptions. You must have two separate except clauses everywhere.

See also the PythonAsJavaException class in my later.py script–necessary if you want to push python stack traces into Ignition loggers.

3 Likes

What about

import traceback
traceback.format_exc()

Phil? Does this miss something?

It doesn’t play nice with the logging system. For loggers to deliver a neat traceback, you have to supply a subclass of java’s Throwable.

1 Like

Thank you, yes, the (message) property of the e object. You mentioned that (if e does not have a message property). What types of errors or when would e not have the message property?

My snippet is from an Ignition UDT script. There are not any (from java.lang import Exception) lines, or anything similar in the scripts.

Can you give an example of what that would look like (two except clauses).
I want to catch errors on system.tag.write, and try: / except: is not catching the error.

The vision client user does not have writePermissions for the first tag in this list, so I want the whole
routine to end. I'm printing to the console to debug what is happening, and I still get an error popup on the client, and I never get the "Error occurred" message in the console which indicates the Except code is NOT RUNNING.

Here is my code:

image

That's because a write that fails is not an error per se. You need to store the return from each write and check if the value is good or not

4 Likes

As Nick said, a failed write doesn't raise an exception, so there's nothing to catch.

I use this to check for failed writes:

base_logger = system.util.getLogger("Utils").createSubLogger("Tags")

def write(paths, values, logger=None):
	if logger is None:
		logger = base_logger
	write_return = system.tag.writeBlocking(paths, values)
	bad_writes = ["{} ({})".format(path, quality) for path, quality in zip(paths, write_return) if not quality.good]
	if bad_writes:
		logger.warn("failed writes: {}".format(bad_writes))

This logs a warning with the path and quality of every failed writes. You might want to rework it a bit to match your needs.