Maya线程导致崩溃
Maya threading causing crash
我已经启动了一个自动保存脚本编辑器脚本(使用 Maya 2014),但它真的很不稳定,如果在保存的同时发生某些事情,它可能会崩溃。我也刚刚意识到即使不保存也会发生崩溃,所以我试图找出真正的问题是什么,最后几乎没有留下任何代码但仍然能够复制它。
我对代码的想法是运行一个后台线程,它会循环并每隔一段时间备份脚本,但每秒检查一个值以确保它没有被暂停或取消(取消将停止循环)。
我认为问题与后台线程在 Maya 中的工作方式有关,因为如果 loading/closing 脚本编辑器 window 或在渲染视图设置上切换选项卡(位于至少选择了 Mental Ray,因为它似乎比默认渲染器需要更长的加载选项卡)。我想还有其他方法,但这些方法确实很容易找到。
在 while 循环中将它降到 time.sleep()
之后,我真的不明白为什么它会导致崩溃。我还使用了另一个 while time.time()>startTime+1
的睡眠函数来确保它不是时间模块,但它仍然导致崩溃。
如果有人想尝试的话,这里是简化的代码,一旦你用 AutoSave.start()
启动线程,如果你不断地加载和关闭脚本编辑器 window,你最终应该会得到一个运行时间错误(表示R6025纯虚函数调用)。这可能需要多次尝试,但它似乎总是最终会发生。
import threading, time
import pymel.core as pm
class AutoSaveThread(object):
def __init__( self ):
thread = threading.Thread(target=self.run, args=())
thread.daemon = True
thread.start()
def run(self):
while True:
time.sleep(1)
print "Open and close the script editor enough times and this will crash"
class AutoSave:
@classmethod
def start( self ):
AutoSaveThread()
我打开了十几个左右的标签页,所以 loading/closing 比 none 花费的时间要长一些,这可能会增加 window 发生崩溃的时间。
作为记录,这里是 Maya 中内置的代码位,只要脚本编辑器 window 关闭,它总是 运行。我以为这可能与我修改后的保存版本有关,然后尝试同时保存,但它仍然崩溃,循环中没有发生任何事情。
global proc syncExecuterBackupFiles(){
global string $gCommandExecuter[];
global string $executerBackupFileName;
if(`optionVar -q saveActionsScriptEditor`) {
// clear the script editor temp dir first before writing temp files
string $scriptEditorTempDir = (`internalVar -userPrefDir` + "scriptEditorTemp/");
string $tempFiles[] = `getFileList -folder $scriptEditorTempDir`;
string $file;
for ($file in $tempFiles) {
sysFile -delete ($scriptEditorTempDir + $file);
}
// save all the executer control text to files
int $i = 0;
for($i = 0; $i < size($gCommandExecuter); $i++) {
cmdScrollFieldExecuter -e -storeContents $executerBackupFileName $gCommandExecuter[$i];
}
}
}
尝试将对 print
的调用包装在 pymel.mayautils.executeDeferred
或 maya.utils.executeDeferred
中,以便它在主 UI 线程上执行。
if you continuously load and close the script editor window, you should eventually get a runtime error (that says R6025 pure virtual function call). It may take multiple attempts, but it always seems to eventually happen.
我能够在 Maya 2012 上确认此行为,但我怀疑它是特定于版本的。
我敢打赌,您对 print
的测试调用实际上是导致 Maya 崩溃的原因,因为尽管 print
通常只是一个 python 语句,但 Maya 有某种挂钩它以使用您正在打印的字符串更新脚本编辑器的输出 Window(可能还有命令响应栏),这两个 运行 在主 UI 线程上。
来自Autodesk Knowledge article "Python and threading":
Maya API and Maya Command architectures are not thread-safe. Maya commands throw an exception if they are called outside the main thread, and use of the OpenMaya API from threads other than the main one has unforeseen side effects.
通过将您的 print
语句传递给 pymel.mayautils.executeDeferred 我(至少到目前为止,谁知道 Maya ;-) )无法导致崩溃。
import threading, time
import pymel.core as pm
import pymel.mayautils # like maya.utils, for executeDeferred
# Set to False at any time to allow your threads to stop
keep_threads_alive = True
def wrapped_print():
print "Opening and closing the script editor shouldn't make this crash\n"
class AutoSaveThread(object):
def __init__(self):
thread = threading.Thread(target=self.run)
thread.start()
def run(self):
while keep_threads_alive:
time.sleep(1)
pymel.mayautils.executeDeferred(wrapped_print)
...
专门包装 print
语句的唯一副作用是它不再回显命令响应栏。如果保留该行为对您很重要,请改用 pymel.mel.mprint
。
import threading
import time
import maya.utils as utils
run_timer = True
run_num = 0
def example(interval = 10):
global run_timer;global run_num;
def your_function_goes_here():
print "hello",run_num
run_num +=1
while run_timer:
time.sleep(interval)
utils.executeDeferred(your_function_goes_here)
t = threading.Thread(None, target = example, args = (1,) )
t.start()
# stop :
# run_timer = False
我已经启动了一个自动保存脚本编辑器脚本(使用 Maya 2014),但它真的很不稳定,如果在保存的同时发生某些事情,它可能会崩溃。我也刚刚意识到即使不保存也会发生崩溃,所以我试图找出真正的问题是什么,最后几乎没有留下任何代码但仍然能够复制它。
我对代码的想法是运行一个后台线程,它会循环并每隔一段时间备份脚本,但每秒检查一个值以确保它没有被暂停或取消(取消将停止循环)。
我认为问题与后台线程在 Maya 中的工作方式有关,因为如果 loading/closing 脚本编辑器 window 或在渲染视图设置上切换选项卡(位于至少选择了 Mental Ray,因为它似乎比默认渲染器需要更长的加载选项卡)。我想还有其他方法,但这些方法确实很容易找到。
在 while 循环中将它降到 time.sleep()
之后,我真的不明白为什么它会导致崩溃。我还使用了另一个 while time.time()>startTime+1
的睡眠函数来确保它不是时间模块,但它仍然导致崩溃。
如果有人想尝试的话,这里是简化的代码,一旦你用 AutoSave.start()
启动线程,如果你不断地加载和关闭脚本编辑器 window,你最终应该会得到一个运行时间错误(表示R6025纯虚函数调用)。这可能需要多次尝试,但它似乎总是最终会发生。
import threading, time
import pymel.core as pm
class AutoSaveThread(object):
def __init__( self ):
thread = threading.Thread(target=self.run, args=())
thread.daemon = True
thread.start()
def run(self):
while True:
time.sleep(1)
print "Open and close the script editor enough times and this will crash"
class AutoSave:
@classmethod
def start( self ):
AutoSaveThread()
我打开了十几个左右的标签页,所以 loading/closing 比 none 花费的时间要长一些,这可能会增加 window 发生崩溃的时间。
作为记录,这里是 Maya 中内置的代码位,只要脚本编辑器 window 关闭,它总是 运行。我以为这可能与我修改后的保存版本有关,然后尝试同时保存,但它仍然崩溃,循环中没有发生任何事情。
global proc syncExecuterBackupFiles(){
global string $gCommandExecuter[];
global string $executerBackupFileName;
if(`optionVar -q saveActionsScriptEditor`) {
// clear the script editor temp dir first before writing temp files
string $scriptEditorTempDir = (`internalVar -userPrefDir` + "scriptEditorTemp/");
string $tempFiles[] = `getFileList -folder $scriptEditorTempDir`;
string $file;
for ($file in $tempFiles) {
sysFile -delete ($scriptEditorTempDir + $file);
}
// save all the executer control text to files
int $i = 0;
for($i = 0; $i < size($gCommandExecuter); $i++) {
cmdScrollFieldExecuter -e -storeContents $executerBackupFileName $gCommandExecuter[$i];
}
}
}
尝试将对 print
的调用包装在 pymel.mayautils.executeDeferred
或 maya.utils.executeDeferred
中,以便它在主 UI 线程上执行。
if you continuously load and close the script editor window, you should eventually get a runtime error (that says R6025 pure virtual function call). It may take multiple attempts, but it always seems to eventually happen.
我能够在 Maya 2012 上确认此行为,但我怀疑它是特定于版本的。
我敢打赌,您对 print
的测试调用实际上是导致 Maya 崩溃的原因,因为尽管 print
通常只是一个 python 语句,但 Maya 有某种挂钩它以使用您正在打印的字符串更新脚本编辑器的输出 Window(可能还有命令响应栏),这两个 运行 在主 UI 线程上。
来自Autodesk Knowledge article "Python and threading":
Maya API and Maya Command architectures are not thread-safe. Maya commands throw an exception if they are called outside the main thread, and use of the OpenMaya API from threads other than the main one has unforeseen side effects.
通过将您的 print
语句传递给 pymel.mayautils.executeDeferred 我(至少到目前为止,谁知道 Maya ;-) )无法导致崩溃。
import threading, time
import pymel.core as pm
import pymel.mayautils # like maya.utils, for executeDeferred
# Set to False at any time to allow your threads to stop
keep_threads_alive = True
def wrapped_print():
print "Opening and closing the script editor shouldn't make this crash\n"
class AutoSaveThread(object):
def __init__(self):
thread = threading.Thread(target=self.run)
thread.start()
def run(self):
while keep_threads_alive:
time.sleep(1)
pymel.mayautils.executeDeferred(wrapped_print)
...
专门包装 print
语句的唯一副作用是它不再回显命令响应栏。如果保留该行为对您很重要,请改用 pymel.mel.mprint
。
import threading
import time
import maya.utils as utils
run_timer = True
run_num = 0
def example(interval = 10):
global run_timer;global run_num;
def your_function_goes_here():
print "hello",run_num
run_num +=1
while run_timer:
time.sleep(interval)
utils.executeDeferred(your_function_goes_here)
t = threading.Thread(None, target = example, args = (1,) )
t.start()
# stop :
# run_timer = False