I've created a module with a single class that creates a graph using matplotlib. This is how I initialize the class and create the graph:
- Code: Select all
def createGraphFromDev(self, devId):
theGraph = stategrapher.DateValueLineGraph(devId, self.pluginPrefs['DatabaseFile'], self.logger)
theGraph.create_graph()
The dev (devId) contains in its properties all of the information needed to create the graph.
- Code: Select all
import matplotlib.pyplot as plt
class DateValueLineGraph():
########################################
def __init__(self, devId, database_file, logger):
self.logger = logger
self._dev = indigo.devices[int(devId)]
self._database_file = database_file
self._fig, self._ax = plt.subplots()
...
This all works fine, however, it's a little slow. It makes several queries to an sqlite database to get the data then creates the graph. I'm trying to move the graph creation into runConcurrentThread() so nothing is blocked while the graph is created. So I setup a queue and put the job in the queue:
- Code: Select all
def createGraphFromDev(self, devId):
self.jobQueue.put(devId)
Then I moved the two lines of code to runConcurrentThread() to create the graph:
- Code: Select all
def runConcurrentThread(self):
try:
while True:
if not self.jobQueue.empty():
devId = self.jobQueue.get()
theGraph = stategrapher.DateValueLineGraph(devId, self.pluginPrefs['DatabaseFile'], self.logger)
theGraph.create_graph()
self.sleep(1)
except self.StopThread:
self.logger.debug(u"runConcurrentThread() exception StopThread")
When I try to create the graph, I get this error:
- Code: Select all
State Grapher Error Error in plugin execution runConcurrentThread
State Grapher Error plugin runConcurrentThread function returned or failed (will attempt again in 10 seconds)
Since there was no helpful error message, I tried reloading the plugin in the Interactive Shell. When run in the interactive shell, the line of code that causes an error is a simple import:
- Code: Select all
import matplotlib.pyplot as plt
In the interactive shell, this message is displayed when the code gets to the import statement:
- Code: Select all
Connected to Indigo Server v7.4.1, api v2.3 (localhost:1176)
Started Plugin State Grapher v0.0.390
>>> 2020-07-31 14:37:52.164 IndigoPluginHost[6915:97316] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'nextEventMatchingMask should only be called from the Main Thread!'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff35746be7 __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff6e3855bf objc_exception_throw + 48
2 AppKit 0x00007fff3293eb65 +[NSEvent _discardTrackingAndCursorEventsIfNeeded] + 0
3 _macosx.so 0x0000000107e16a8d init_macosx + 1206
4 readline.so 0x0000000106b5ac8e initreadline + 950
5 Python 0x00007fff408370b2 PyOS_Readline + 179
6 Python 0x00007fff408b21f2 _PyBuiltin_Init + 12167
7 Python 0x00007fff408b8bbf PyEval_EvalFrameEx + 18888
8 Python 0x00007fff408b3bec PyEval_EvalCodeEx + 531
9 Python 0x00007fff408bd6ea _PyEval_SliceIndexNotNone + 459
10 Python 0x00007fff408b8b00 PyEval_EvalFrameEx + 18697
11 Python 0x00007fff408b3bec PyEval_EvalCodeEx + 531
12 Python 0x00007fff4085aaa8 PyFunction_SetClosure + 772
13 Python 0x00007fff4083d143 PyObject_Call + 97
14 _functools.so 0x0000000106a297ee init_functools + 470
15 Python 0x00007fff4083d143 PyObject_Call + 97
16 Python 0x00007fff408b9276 PyEval_EvalFrameEx + 20607
17 Python 0x00007fff408bd68f _PyEval_SliceIndexNotNone + 368
18 Python 0x00007fff408b8b00 PyEval_EvalFrameEx + 18697
19 Python 0x00007fff408bd68f _PyEval_SliceIndexNotNone + 368
20 Python 0x00007fff408b8b00 PyEval_EvalFrameEx + 18697
21 Python 0x00007fff408b3bec PyEval_EvalCodeEx + 531
22 Python 0x00007fff4085aaa8 PyFunction_SetClosure + 772
23 Python 0x00007fff4083d143 PyObject_Call + 97
24 Python 0x00007fff408478f4 PyMethod_New + 1169
25 Python 0x00007fff4083d143 PyObject_Call + 97
26 Python 0x00007fff408bcfeb PyEval_CallObjectWithKeywords + 159
27 Python 0x00007fff408e940b initthread + 2815
28 Python 0x00007fff408e5103 PyThread_start_new_thread + 279
29 libsystem_pthread.dylib 0x00007fff6f731109 _pthread_start + 148
30 libsystem_pthread.dylib 0x00007fff6f72cb8b thread_start + 15
)
libc++abi.dylib: terminating with uncaught exception of type NSException
/Library/Application Support/Perceptive Automation/Indigo 7.4/.debugPluginLaunch.command: line 7: 6915 Abort trap: 6 "/Library/Application Support/Perceptive Automation/Indigo 7.4/IndigoPluginHost.app/Contents/MacOS/IndigoPluginHost" -d200 -p1176 -f"State Grapher.indigoPlugin"
Here's some additional information. Just for testing purposes, I commented out the line of code that imports the module for graphing and I commented out the code that calls it. I then moved the include statement to plugin.py (instead of in the module). Even running this in the interactive shell causes the same error. This leads me to believe that there are two different problems going on here.
- For whatever reason, you can't run the plugin in the interactive shell if it includes matplotlib.pyplot.
- The other problem, which may or may not be related, is that the code still errors out when it is not run in the interactive shell. In this scenario, the code does not have a problem with the include statement, but errors out when trying to initialize self._fig and self._ax:
- Code: Select all
import matplotlib.pyplot as plt
class DateValueLineGraph():
########################################
def __init__(self, devId, database_file, logger):
self.logger = logger
self._dev = indigo.devices[int(devId)]
self._database_file = database_file
self._fig, self._ax = plt.subplots()
...
Any thoughts? I don't even know where to begin with this one.