Poll evasion when accessing Matlab from Python

I would like to access Matlab from Python (on Windows, remotely and through the COM interface). My goal: Matlab does some work and constantly changes the value of a specific variable. I need to know when a value exceeds some constant. Right now, I am processing Matlab for the value of this variable in an undefined loop that will interrupt the excess of the value. However, I would like to let Matlab do the work and tell me when it is, while I sit idly while listening. Is there a way to achieve this, and how is this best done? I was thinking about defining a callback function that I pass to Matlab that, on triggers with an excess, causes a wait loop to break without waiting in Python, but I doubt it will work. I am not very experienced in either Matlab or Python, so replicas are very much appreciated.

There is a lot of other code, but basically right now it looks like

connectToMatlab(*args) while True: val = getValueFromMatlab() if val > constant or timeout: break 

What I mean is

 def breakLoop(): ... connectToMatlab(breakLoop, *args) while True: time.sleep(1) # or some alternate non-busy-wait 

and then let Matlab call breakLoop() after val > constant . However, I do not know if it is possible to allow Matlab to do this with a callback, and if so, how to implement such a breakLoop() function.

+2
source share
1 answer

You can work around this in another way and use the file system as a way to transfer messages between MATLAB and Python.

Inside your MATLAB code, every time you change a variable, check to see if it exceeds a certain threshold. If so, create a new file in a specific location. Think of it as triggering an event.

Now, while inside your Python code, use some of the available ways to listen for changes in the file system and respond by specifying some variable to break the loop.


EDIT

Here is the skeleton of the proposed solution:

matlab_script.m

 %# directory that Python code is watching for modifications dirPath = 'some_directory'; x = 0; for i=1:1000 %# some lengthy operation pause(0.5) x = x + 1; %# check if variable exceeds threshold if x > 10 %# save the workspace to MAT-file inside the directory watched. %# this shall trigger the notification in Python save( fullfile(dirPath,'out.mat') ) break end end 

python_code.py

 import os, sys, time import win32file, win32event, win32con # stub your functions in my case def connectToMatlab(): pass def getValueFromMatlab(): return 99 # path to predetermined directory to watch dirPath = "some_directory" dirPath = os.path.abspath(dirPath) # start/connect to a MATLAB session, running the script above connectToMatlab() # set up folder watching (notify on file addition/deletion/renaming) print "Started watching '%s' at %s" % (dirPath, time.asctime()) change_handle = win32file.FindFirstChangeNotification( dirPath, 0, win32con.FILE_NOTIFY_CHANGE_FILE_NAME) # time-out in 10 sec (win32event.INFINITE to wait indefinitely) timeout = 10000 try: # block/wait for notification result = win32event.WaitForSingleObject(change_handle, timeout) # returned because of a change notification if result == win32con.WAIT_OBJECT_0: # retrieve final result from MATLAB print "MALTAB variable has exceeded threshold at %s" % time.asctime() val = getValueFromMatlab() # timed out elif result == win32con.WAIT_TIMEOUT: print "timed-out after %s msec at %s" % (timeout,time.asctime()) val = None # maybe to indicate failure finally: # cleanup properly win32file.FindCloseChangeNotification(change_handle) # work with val print val 

The WaitForSingleObject function is started by checking the status of the specified object. If it is not signaled, the calling thread goes into an effective waiting state and consumes very little processor time, waiting until the object is signaled (or the timeout interval has expired).

You see, when a thread refers to an object that is in a state without signaling, there is an immediate context switch, that is, it is removed from the processor and put into standby / sleep mode. Later, when the object is signaled, the thread returns to the execution queue and is ready to execute.

In this form of waiting, there is no loss in the CPU cycle in the idle state, although there is some overhead when switching contexts.

Contrast this with the polling and waiting approach, when a thread is waiting and checking the state of an object of interest in a loop. This is known as waiting for a wait or waiting, which can be a loss of processor cycles.

Now, thanks to the pywin32 module, we can use the WaitFor... functions directly. The implementation should be a simple port standard example specified in MSDN.

Alternatively, you can use the PyQt library with the QFileSystemWatcher class instead of directly using the Win32 API.

+2
source

Source: https://habr.com/ru/post/952476/


All Articles