Odd errors concerning large modules

Below is the error I receive when I try to access a list defined in a module called EpsonRC.Data

What's it's origin and how does one correct it?

Traceback (most recent call last):
File "event:propertyChange", line 2, in
java.lang.RuntimeException: Module or method too large in <module:EpsonRC.Data>.
Please provide a CPython 2.7 bytecode file (.pyc), e.g. run
python -m py_compile module:EpsonRC.Data
Alternatively, specify a CPython 2.7 command via the python.cpython2 property, e.g.:
jython -Dpython.cpython2=python
or (e.g. for pip) through the environment variable JYTHON_OPTS:
export JYTHON_OPTS="-Dpython.cpython2=python"

java.lang.RuntimeException: java.lang.RuntimeException: Module or method too large in <module:EpsonRC.Data>.
Please provide a CPython 2.7 bytecode file (.pyc), e.g. run
python -m py_compile module:EpsonRC.Data
Alternatively, specify a CPython 2.7 command via the python.cpython2 property, e.g.:
jython -Dpython.cpython2=python
or (e.g. for pip) through the environment variable JYTHON_OPTS:
export JYTHON_OPTS="-Dpython.cpython2=python"

caused by RuntimeException: Module or method too large in `module:EpsonRC.Data`.

Please provide a CPython 2.7 bytecode file (.pyc), e.g. run
python -m py_compile module:EpsonRC.Data

Alternatively, specify a CPython 2.7 command via the python.cpython2 property, e.g.:
jython -Dpython.cpython2=python
or (e.g. for pip) through the environment variable JYTHON_OPTS:
export JYTHON_OPTS="-Dpython.cpython2=python"

Ignition v8.1.44 (b2024102210)
Java: Azul Systems, Inc. 17.0.12

Ignition uses Jython, which doesn't support CPython modules.

I'm not sure of all the CPython stuff is the issue or a distraction.

It seems the real problem might be this:

 java.lang.RuntimeException: Module or method too large in <module:EpsonRC.Data>.

This is the root cause. So what are the limits of a module? And why are there limits at all?

The module EpsonRC.Data is a very large and follows the example

errorCodes = [[code, message, note1, note2], [code, message, note1, note2], [code, message, note1, note2], .......]

I'm assuming the work around would be to break my the module into separate smaller modules?

Java itself has a limit of 65kb on method sizes, not sure what the Jython limits are, but it's probably related.

You'll have to break it up, yes.

Ideally you refactor so that you aren't storing a large amount of data as code. Store it in a file, database, etc... and do a lookup. Or load it once at runtime into a dictionary, but don't write/store it as a mass of literal code.

4 Likes

I'm not the biggest fan of storing the data outside of Ignition. Standardizing projects with items not contained in a project can be tedious and hard to manage in the future (i.e. external text files or databases). Thank you for the suggestions!

In some future version of Ignition we're planning to add an arbitrary 'file' resource type that you could use to address this kind of persistent data-attached-to-project use case.

In the meantime, you really should come up with a better approach than storing it in massive code files. The Jython interpreter is relatively slow, and you're doing the rest of your system no favors making it chew on these massive script file(s) every time the interpreter restarts (which is more or less every time you save any changes to your project).

I would put the data into a SQLite DB; if you use the special ${data} placeholder we'll automatically use a localized path that will be included in a gateway backup, so you only have to manually ingest the data once:

This was my first consideration but I'm working in Edge so it's not an option. I ended up shoving the data into a .txt file and wrote some code to access it.

For anyone interested that code is below.

import ast
with open('C:/IgnitionData/codes.txt', 'r') as f:
	for line in f:
		# Evaluate the string to get an actual list
		row = ast.literal_eval(line.strip())
		if int(row[0]) == event.newValue:
			event.source.getComponent('Label').text = str(row[0])
			event.source.getComponent('Label 1').text = str(row[1])
			event.source.getComponent('Label 2').text = str(row[2])
			break

Consider using a json file instead of a custom text file. Will allow you to include structured constants without any extra code.

1 Like

Or even just CSV. I'd take any known standard lingua franca format over ast.literal_eval :see_no_evil:

2 Likes