# Generic Python error handler?

**URL:** <https://forum.inductiveautomation.com/t/generic-python-error-handler/60584>\
**Category:** Ignition\
**Tags:** ignition81, scripting\
**Created:** [June 9, 2022, 9:06pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584 "2022-06-09T21:06:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rvaught](https://avatars.discourse-cdn.com/v4/letter/r/b487fb/32.png) [@rvaught](https://forum.inductiveautomation.com/u/rvaught)\
**Post date:** [June 9, 2022, 9:06pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/1 "2022-06-09T21:06:14Z")

</div>

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?

```auto
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?

```

---

<div class="post-metadata">

**Author:** ![zacht](https://avatars.discourse-cdn.com/v4/letter/z/ea5d25/32.png) [@zacht](https://forum.inductiveautomation.com/u/zacht)\
**Post date:** [June 9, 2022, 9:10pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/2 "2022-06-09T21:10:57Z")

</div>

> [@Import not Work](https://forum.inductiveautomation.com/t/import-not-work/24063/2):
>
> Jython’s Exception class does not inherit from Java’s base exception class - so exceptions thrown in Java code (ie, everything written by Inductive Automation) are not caught by Exception clauses. You have to catch both possible exceptions: import java.lang.Exception try: # something something something except Exception, e: # jython exception except java.lang.Exception, e: or import java.lang.Exception try: # something something something except (Exception, java.lang.Exception),…

---

<div class="post-metadata">

**Author:** ![rvaught](https://avatars.discourse-cdn.com/v4/letter/r/b487fb/32.png) [@rvaught](https://forum.inductiveautomation.com/u/rvaught)\
**Post date:** [June 9, 2022, 9:34pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/3 "2022-06-09T21:34:04Z")

</div>

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](https://us1.discourse-cdn.com/inductiveautomation/original/3X/5/2/52e6c090ef6273c843902112a1a0148885a327ab.png)

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

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 9, 2022, 10:29pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/4 "2022-06-09T22:29:08Z")

</div>

`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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 10, 2022, 12:50am UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/5 "2022-06-10T00:50:34Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [June 10, 2022, 12:19pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/6 "2022-06-10T12:19:59Z")

</div>

What about

```auto
import traceback
traceback.format_exc()

```

Phil? Does this miss something?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 10, 2022, 12:46pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/7 "2022-06-10T12:46:05Z")

</div>

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`.

---

<div class="post-metadata">

**Author:** ![rvaught](https://avatars.discourse-cdn.com/v4/letter/r/b487fb/32.png) [@rvaught](https://forum.inductiveautomation.com/u/rvaught)\
**Post date:** [June 10, 2022, 2:11pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/8 "2022-06-10T14:11:21Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![rsonnicksen](https://avatars.discourse-cdn.com/v4/letter/r/8e8cbc/32.png) [@rsonnicksen](https://forum.inductiveautomation.com/u/rsonnicksen)\
**Post date:** [December 30, 2022, 5:21pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/9 "2022-12-30T17:21:52Z")

</div>

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](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/3/23f9728079942914ba37bde50e475375c63fe638.png)

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [December 31, 2022, 6:15am UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/10 "2022-12-31T06:15:31Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [January 3, 2023, 9:16am UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/11 "2023-01-03T09:16:04Z")

</div>

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:

```python
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.

---

<div class="post-metadata">

**Author:** ![tkiley](https://avatars.discourse-cdn.com/v4/letter/t/bbe5ce/32.png) [@tkiley](https://forum.inductiveautomation.com/u/tkiley)\
**Post date:** [July 11, 2024, 7:56pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/12 "2024-07-11T19:56:52Z")

</div>

Hey Phil, I'm looking for a little clarification on this post.

We currently use `Except` and `from java.lang.import Exception` to catch both Python and Java exceptions.The way I'm interpreting your post is that you have since switched to `Throwable` since it is able to catch both Java and Python's exceptions.

After some quick tests I'm starting to think I read/understood this incorrectly, but I'm still clinging tightly to the hope that I'll be vindicated in my initial understanding (oh how I'd love to remove an `except` clause)... care to raise me up or tear me down?

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [July 11, 2024, 8:10pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/13 "2024-07-11T20:10:27Z")

</div>

> [@tkiley](#):
>
> The way I'm interpreting your post is that you have since switched to `Throwable` since it is able to catch both Java and Python's exceptions.

Throwable is a Java class and as such has nothing to do with Python errors.

Not to answer for Phil, but as I understand he has switched to Throwable because all **Java** exceptions and errors inherit from Throwable. Which makes the except for **Java** exceptions more robust. It does not remove the need for a second except clause for Python Exceptions.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 11, 2024, 8:14pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/14 "2024-07-11T20:14:20Z")

</div>

> [@lrose](#):
>
> Which makes the except for **Java** exceptions more robust. It does not remove the need for a second except clause for Python Exceptions.

Entirely correct. It also eliminates the clash between the python and java `Exception` name.

---

<div class="post-metadata">

**Author:** ![tkiley](https://avatars.discourse-cdn.com/v4/letter/t/bbe5ce/32.png) [@tkiley](https://forum.inductiveautomation.com/u/tkiley)\
**Post date:** [July 11, 2024, 8:50pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/15 "2024-07-11T20:50:55Z")

</div>

Ok, this confirms my suspicions. I ended up going this route to remove the double except clause..

```python
import java.lang.Exception
try:
    #some code
except (Exception, java.lang.Exception) as e:
	if isinstance(e, java.lang.Exception):
		message = e.getMessage()
	else:
		message = str(traceback.format_exc())

```

Thanks for the discussion.  
edit: I wonder what the implications will be if the code throws both...guessing that's why no one has done this elsewhere, thoughts?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 11, 2024, 8:52pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/16 "2024-07-11T20:52:42Z")

</div>

> [@tkiley](#):
>
> I ended up going this route to remove the double except clause..

Why?

The separate except clauses will execute far faster, as the implementation does the class checking without needing to invoke the interpreter to run `isinstance()`.

Just use the two clauses. Really.

Also, you really want to use loggers to report exceptions of any kind, so you get neat tracebacks. Using the separate clauses makes use of my `PythonAsJavaException()` class really easy.

---

<div class="post-metadata">

**Author:** ![tkiley](https://avatars.discourse-cdn.com/v4/letter/t/bbe5ce/32.png) [@tkiley](https://forum.inductiveautomation.com/u/tkiley)\
**Post date:** [July 11, 2024, 8:57pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/17 "2024-07-11T20:57:06Z")

</div>

Hey that makes some sense, but what exactly does "far faster" mean in a situation like this?

Also fair point on the logger comment, I'm strictly using the `message` variable to supply a popup that the user will get to report errors. Should probably add the logger piece in there as well so we have more information to go off of.

edit: I'll take a peak at your class if you let me know where to find it!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 11, 2024, 8:58pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/18 "2024-07-11T20:58:52Z")

</div>

[https://www.automation-pros.com/ignition/later.py](https://www.automation-pros.com/ignition/later.py)

There's probably a zillion references to this on the forum.

---

<div class="post-metadata">

**Author:** ![Ryan\_Deardorff](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryan_deardorff/32/63815_2.png) [@Ryan\_Deardorff](https://forum.inductiveautomation.com/u/Ryan_Deardorff)\
**Post date:** [July 12, 2024, 1:24pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/19 "2024-07-12T13:24:47Z")

</div>

When I saw your example there I thought, hey, that looks just like the error handling I inherited from my predecessor, they must have both followed the same example from somewhere. Then I noticed your username. You _are_ my predecessor! 😂

FWIW, I have had no problems using `str(e)` instead of `getattr` for either Python or Java Exceptions.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [July 12, 2024, 1:40pm UTC](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584/20 "2024-07-12T13:40:05Z")

</div>

> [@tkiley](#):
>
> if the code throws both

Not sure what you mean by this. Once any exception is thrown/raised, no further exception can be thrown by that original code. So only one `except` clause will ever fire at a single time.

(Exception handlers can throw/raise their own errors, but those get caught by the next enclosing `try:` block.)

[Next page](https://forum.inductiveautomation.com/t/generic-python-error-handler/60584.md?page=2)
