# Getting error line number from sys.exc\_info

**URL:** <https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252>\
**Category:** Ignition\
**Created:** [May 23, 2019, 1:04am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252 "2019-05-23T01:04:12Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![richardNZ15](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/richardnz15/32/33373_2.png) [@richardNZ15](https://forum.inductiveautomation.com/u/richardNZ15)\
**Post date:** [May 23, 2019, 1:04am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/1 "2019-05-23T01:04:12Z")

</div>

Hi i've seen other threads recommend providing error reporting using code like;  
`system.gui.errorBox("%s, %s"% (sys.exc_info()[0],sys.exc_info()[1]))`  
But that doesn't provide offending line number which can be very handy.

For example the following code:

```auto
try:
	# some code
except:
	import sys
	logger.error(str(sys.exc_info()))

```

outputs:

> 12:58:53.082 [Thread-31] ERROR com.inductiveautomation.factorypmi.application.script.builtin.WindowUtilities - \<type 'exceptions.TypeError'\>, getValueAt(): 1st arg can't be coerced to int

But if i don't have any try/catch code, i get the following output from the Error popup (compact details):

> Traceback (most recent call last):
> 
> File "", line 58, in calcQnty
> 
> TypeError: getValueAt(): 1st arg can't be coerced to int
> 
> Ignition v7.9.9 (b2018081621)  
> Java: Oracle Corporation 1.8.0\_101

Is there anyway to get the line number out when writing exception handling?  
Thank very much!

---

<div class="post-metadata">

**Author:** ![richardNZ15](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/richardnz15/32/33373_2.png) [@richardNZ15](https://forum.inductiveautomation.com/u/richardNZ15)\
**Post date:** [May 23, 2019, 1:51am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/2 "2019-05-23T01:51:48Z")

</div>

I have come up with the following approach for 'catch all' error handling of unexpected errors using this as reference:

> <https://stackoverflow.com/questions/6961750/locating-the-line-number-where-an-exception-occurs-in-python-code/6961780#6961780>

```auto
import sys
import traceback

logger = system.util.getLogger("ScriptDebugging")

# Some identifier for script name. 'calcQnty' is a custom method on a button component
scriptName = self.name + ".calcQnty"
try:
	# Some code
except:
	exType, ex, tb = sys.exc_info()
	logger.error("ERROR in '%s' line %d: %s, %s" % (scriptName,traceback.tb_lineno(tb), exType, ex))

```

Provides the following output which i think provides all the info I would need to debug:

> 13:47:12.268 [Thread-39] ERROR ScriptDebugging - ERROR in 'Button Calc Volume.calcQnty' line 61: \<type 'exceptions.TypeError'\>, getValueAt(): 1st arg can't be coerced to int

---

<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:** [May 23, 2019, 11:27am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/3 "2019-05-23T11:27:20Z")

</div>

You might want to look at my Java wrapper for python exceptions that is part of [later.py](https://www.automation-pros.com/ignition/later.py). You can pass it to a logger to expand into a java-style traceback.

---

<div class="post-metadata">

**Author:** ![richardNZ15](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/richardnz15/32/33373_2.png) [@richardNZ15](https://forum.inductiveautomation.com/u/richardNZ15)\
**Post date:** [May 27, 2019, 5:01am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/4 "2019-05-27T05:01:31Z")

</div>

Thanks Phil,  
Had a look but i think its a bit over my head to use that wrapper!

---

<div class="post-metadata">

**Author:** ![marcelo.amorim](https://avatars.discourse-cdn.com/v4/letter/m/3bc359/32.png) [@marcelo.amorim](https://forum.inductiveautomation.com/u/marcelo.amorim)\
**Post date:** [January 28, 2025, 12:23am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/5 "2025-01-28T00:23:48Z")

</div>

I know its been years, but for anyone looking for a complete answer here is what worked for me (as always thank you Phill!):

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

### Java wrapper for Jython exceptions to preserve the python stack trace.

```python
class PythonAsJavaException(java.lang.Exception):

	def __init__ (self, pyexc, tb=None):
		super(PythonAsJavaException, self). __init__ (repr(pyexc), None, True, True)
		traceElements = []
		if tb is None:
			tb = sys.exc_info()[2]
		while tb:
			code = tb.tb_frame.f_code
			vnames = code.co_varnames
			if vnames and vnames[0] in ('cls', 'self'):
				ref = tb.tb_frame.f_locals[vnames[0]]
				if vnames[0] == 'self':
					className = fullClassName(ref. __class__ )
				else:
					className = fullClassName(ref)
			else:
				className = '<global>'
			traceElements.append(StackTraceElement(className, code.co_name, code.co_filename, tb.tb_lineno))
			tb = tb.tb_next
		traceElements.reverse()
		self.setStackTrace(traceElements)

```

### Here is my quick and dirty way:

```python

from pturmel.later import PythonAsJavaException

def log_full_exception(logger, message, exception):
    """
    Logs a Python exception as a Java-style traceback using the system.util.getLogger instance.
    
    Args:
        logger (system.util.getLogger): Logger instance to log the exception.
        message (str): Additional context message.
        exception (Exception): Python exception to log.
    """
    try:
        raise PythonAsJavaException(exception)
    except PythonAsJavaException as java_exc:
        logger.error("{}: {}".format(message, exception), java_exc)

# Set up the logger
my_logger = system.util.getLogger("Test")

try:
    # Simulate an exception
    1/0
except Exception as e:
    log_full_exception(my_logger, "An error occurred", e)

```

### Here is an example of the output:

```python
ERROR Test -- An error occurred: integer division or modulo by zero
org.python.proxies.later$PythonAsJavaException$3: ZeroDivisionError('integer division or modulo by zero',)
	at <global>.<module>(<input>:25)

```

---

<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:** [January 28, 2025, 4:58am UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/6 "2025-01-28T04:58:32Z")

</div>

_Pssst!_ **One**"L".

---

<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:** [March 26, 2026, 12:36pm UTC](https://forum.inductiveautomation.com/t/getting-error-line-number-from-sys-exc-info/25252/7 "2026-03-26T12:36:12Z")

</div>

FWIW, a better, faster implementation of `PythonAsJavaException` is supplied in my Integration Toolkit as the [system.reflect.asThrowable()](https://www.automation-pros.com/toolkit/doc/reflection.html#pyobject) utility function.
