我想从Python(在Windows上,远程和通过COM接口)访问Matlab。我的目标是:Matlab正在做一些工作并永久地改变某个变量的值。我需要知道值何时超过某个常数。现在,我在一个不确定的循环中轮询Matlab以获取该变量的值,该循环超过了该值。但是,我想让Matlab完成这项工作并告诉 me 在那种情况下,而我懒洋洋地坐在那里听。有没有办法实现这一目标,如何做到最好?我已经考虑过定义一个我正在传递给Matlab的回调函数,它在超级事件中触发了Python中非忙等待循环的突破,但我怀疑它是否会起作用。我在Matlab和Python中都不是很有经验,因此非常感谢cues。
还涉及很多其他代码,但现在基本上就像
connectToMatlab(*args)
while True:
val = getValueFromMatlab()
if val > constant or timeout: break
我想到的是
def breakLoop():
...
connectToMatlab(breakLoop, *args)
while True:
time.sleep(1) # or some alternate non-busy-wait
然后让Matlab在breakLoop()
上调用val > constant
。但是,我不知道是否可以让Matlab通过回调来做到这一点,如果是的话,如何实现这样的breakLoop()
- 函数。
答案 0 :(得分:2)
你可以用另一种方式解决这个问题,并使用文件系统作为在MATLAB和Python之间传递消息的方法。
在MATLAB代码中,每次更改变量时,请检查它是否超过某个阈值。如果是,请在预定位置创建新文件。将此视为触发事件。
现在在python代码中,使用文件系统中listen到changes的一些可用方法,并通过指示一些变量来响应以打破循环。
以下是建议解决方案的框架:
%# 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
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
WaitForSingleObject
函数首先检查指定对象的状态。如果它没有信号,则调用线程进入有效的等待状态,并且在等待对象发出信号(或超时间隔过去)时消耗非常少的处理器时间。
您会看到线程引用处于非信号状态的对象时,会立即进行上下文切换,即从处理器中取下并进入等待/休眠模式。稍后当对象发出信号时,线程将被放回可运行队列并准备好执行。
在这种等待中,在等待状态下没有CPU周期的浪费,尽管在上下文切换中存在一些开销。
将此与“轮询和等待”方法进行比较,其中线程在某种循环中等待并检查感兴趣对象的状态。这被称为旋转或忙等待,这可以证明是CPU周期的浪费。
现在感谢pywin32模块,我们可以直接使用这些WaitFor...
函数。实现应该是MSDN中给出的standard example的简单端口。
或者,您可以将PyQt库与其QFileSystemWatcher类一起使用,而不是直接使用Win32 API。