2015-04-01 185 views
0

我已經啓動了一個自動保存腳本編輯器腳本(使用Maya 2014),但它非常不穩定,並且如果某個事件與保存同時發生,可能會崩潰。我也剛剛意識到即使沒有保存時​​也會發生崩潰,所以我試圖找出實際問題是什麼,最後幾乎沒有任何代碼留下,但仍然能夠複製它。Maya線程導致崩潰

我對代碼的想法是運行一個後臺線程,它會以一定的時間間隔循環和備份腳本,但每秒檢查一次值以確保它沒有被暫停或取消(取消將會停止循環)。

我認爲這個問題與Maya中後臺線程的工作方式有關,因爲如果加載/關閉腳本編輯器窗口或切換渲染視圖設置上的選項卡(至少選擇了Mental Ray,它似乎需要比默認渲染器更長的加載選項卡)。我認爲還有其他方法,但那些是很容易找到的。

在一個while循環中把它歸結爲time.sleep()之後,它對我來說真的沒有意義,因爲它會導致崩潰。我還使用了一個不同的睡眠功能,確保它不是時間模塊,但它仍然導致崩潰。

如果有人想嘗試它,一旦你開始線程AutoSave.start(),如果你不斷加載並關閉腳本編輯器窗口,最終會得到一個運行時錯誤(表示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() 

我有十幾個標籤打開,以便裝載/關閉需要更長的時間比我什麼都沒有,這可能會增加時間窗口,崩潰可能發生。

爲了記錄,這裏是Maya內置的一小段代碼,它將在腳本編輯器窗口關閉時始終運行。我認爲這可能與我的修改版本保存有關,然後嘗試在同一時間保存,但它仍然在循環中沒有任何事情發生。

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]; 
     } 
    } 
} 

回答

3

嘗試,使其在主UI線程上執行的pymel.mayautils.executeDeferredmaya.utils.executeDeferred你的包裹到print電話。


,如果你不斷地加載和關閉腳本編輯器窗口,你應該最終會得到一個運行時錯誤(也稱R6025純虛函數調用)。它可能需要多次嘗試,但似乎總是發生。

我能夠在Maya 2012上確認這種行爲,我懷疑它是否是特定版本。我的打賭是,你對print的測試調用實際上是導致Maya崩潰的原因,因爲即使print通常只是一個python語句,Maya也有一些鉤子來更新腳本編輯器的輸出窗口(和潛在的命令響應欄)與你正在打印的字符串,它們都在主UI線程上運行。

Autodesk Knowledge article "Python and threading"

瑪雅API和Maya指揮架構不是線程安全的。如果在主線程之外調用Maya命令,則會引發異常,並且從主線程以外的線程使用OpenMaya API會產生無法預料的副作用。

通過傳遞您的print聲明pymel.mayautils.executeDeferred我一直無法導致崩潰(至少到目前爲止,誰與瑪雅知道;-))。

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

+0

非常感謝哈哈,我曾試着在'executeDeferred'中包裝其他位,但我並不認爲這是爲了'print'。如果在保存腳本編輯器時加載/關閉腳本編輯器,那麼完整的代碼仍然會崩潰(懷疑我能做的事情還有很多,但警告人們),但是到目前爲止,它似乎還能正常工作。只是好奇,我總是做'maya.utils.executeDeferred',並不知道'pymel.mayautils',是否有優勢嗎?另外,pymel.mel.mprint'通常比裝載pymel的'print'更好用嗎? – Peter 2015-04-01 13:06:28

+0

@Peter您應該能夠完成這項工作而不必擔心崩潰,但這取決於您如何以及何時從腳本編輯器獲取數據。 – systemexit 2015-04-01 14:53:20

+1

@Peter'pymel.mayautils.executeDeferred'是'mel.utils.executeDeferred'的一個封裝,它也處理Maya在批處理模式下運行的情況,'print'是一個python語句,而'mprint'調用'maya .mel.eval'使用mel的打印。我鏈接的pymel文檔解釋了兩者的差異,並且更好,兩者的來源都可以訪問。請參閱Maya安裝中的「Python/lib/site-packages/pymel/mayautils.py」和「Python/lib/site-packages/pymel/core/language.py」。 – systemexit 2015-04-01 15:06:55