如何中止Maya中通过python中的cmds.file启动的文件加载

如何中止Maya中通过python中的cmds.file启动的文件加载,python,maya,maya-api,Python,Maya,Maya Api,我有一些代码可以在Maya中对文件执行批处理操作。实际实现并不重要,只需知道它会收到文件路径列表,maya会打开文件,然后依次对每个文件执行操作 如果引用因任何原因(如无效路径)无效,我希望中止整个场景的加载,并跳到批处理列表中的下一个场景。 看看这个网站和其他地方的其他问题,我只能看到用户询问如何查询参考资料。我已经有了一个合理的函数来执行此操作,它是在该函数返回一个无效的引用路径之后要做的事情,这让我感到困惑 历史上,通过弹出窗口手动解析无效引用路径,但是在大批量情况下,持续监视maya实例

我有一些代码可以在Maya中对文件执行批处理操作。实际实现并不重要,只需知道它会收到文件路径列表,maya会打开文件,然后依次对每个文件执行操作

如果引用因任何原因(如无效路径)无效,我希望中止整个场景的加载,并跳到批处理列表中的下一个场景。

看看这个网站和其他地方的其他问题,我只能看到用户询问如何查询参考资料。我已经有了一个合理的函数来执行此操作,它是在该函数返回一个无效的引用路径之后要做的事情,这让我感到困惑

历史上,通过弹出窗口手动解析无效引用路径,但是在大批量情况下,持续监视maya实例是不可行的。也不是抑制弹出窗口本身,因为我相信它仍然会打开文件,并在其处于无效状态时在场景中运行批处理操作

我已经尝试过不加载引用,但是当使用
loadReferenceDepth
标志和
cmds.file
时,仍然会弹出一个弹出窗口:

cmds.file(r'c:\path\to\file.ma', o=1, f=1, lrd='none')  #invalid ref popup during file cmd
第二种方法是查看并在before open事件上注册回调。下面的代码在功能上与批处理的设置方式相同:

import maya.OpenMaya as OpenM

batchFileList = [r"c:\path\to\file.ma", r"c:\path\to\file2.ma"]

def _test_raise_exception(arg0, arg1, arg2):
    #pretending that a file ref failed below. Ref path validation code would go here.
    print '\n'*5+'Test Logging'+'\n'*5
    return False

cId = OpenM.MSceneMessage.addCheckFileCallback(OpenM.MSceneMessage.kBeforeOpenCheck, _test_raise_exception)

for file_ in batchFileList:
    try:
        rv = cmds.file(file_, o=1)
        #do stuff to the maya scene here
    except:
        #something didn't validate on load, except and skip, logging the occurrence.
        print 'load cancelled'

OpenM.MSceneMessage.removeCallback(cId)
但是,即使已加载,文件仍会加载

同样,替换
raise RUNTIMERROR
return False
也不会让我捕获异常。相反,
cmds.file
完成,只在日志中打印一条小消息,说“python回调失败”

我们已经删除了MStatus类。必须使用Python异常 而不是MStatus

我是不是遗漏了什么?一定有办法做到这一点。构建一个非常粗糙的.ma解析器是另一种选择,但这意味着放弃对.mb文件的支持,我不想这样做


谢谢你的时间

您是否在独立模式下使用
lrd='none'
prompt=0
尝试了
cmds.file
?这应该可以让您在没有对话框的情况下进入文件,这样您就可以在加载引用之前预先检查引用,并在引用被阻塞时跳过该文件。

我在Maya论坛上问过这个问题,并且:

您所指的文档适用于Maya Python API 2,但您使用的类来自Maya Python API 1

在API 1中,大多数方法都采用与C++完全相同的参数。这意味着一个校验FielCalCou后传将通过三个参数,第一个参数是对C++布尔变量的引用。要中止文件加载,必须将该变量设置为false,这需要使用ctypes或MScriptUtil

在API 2中,CheckFileCallback返回True或False以指示是否应继续加载文件。因此,在您的示例中,将“import maya.OpenMaya”更改为“import maya.api.OpenMaya”,并从_test_raise_exception的参数列表中删除一个参数,您就可以开始了

我继续测试它,发现如果我提出一个异常,它会在内部被捕获,并且过程会继续。答案是添加一些outData,在其中设置一个异常,然后检查它是否在之后被命中

import maya.api.OpenMaya as OpenM
batchFileList = [r"c:\path\to\file.ma", r"c:\path\to\file2.ma"]

def _test_raise_exception(fileObject, clientData):
    #pretending that a file ref failed below. Ref path validation code would go here.
    clientData['exception'] = RuntimeError('bad ref {}'.format(fileObject.expandedFullName()))
    return False

for file_ in batchFileList:
    try:
        outData = {} 
        cId = OpenM.MSceneMessage.addCheckFileCallback(OpenM.MSceneMessage.kBeforeCreateReferenceCheck, _test_raise_exception, clientData=outData)
        rv = cmds.file(file_, o=1)
        OpenM.MSceneMessage.removeCallback(cId)
        if 'exception' in outData: #check if an exception was set, if so, raise it
            raise outData['exception']
    except:
        #handle the exception here
        print 'load cancelled'

通过这种方式,我可以在批处理过程中加载我的文件,并以pythonic方式处理失败加载的任何异常。

FWIW,删除MB并不是一个完全疯狂的选择——许多工作室这样做正是出于以下原因:(@theodox我也这么认为,当我需要验证文件而不需要通过maya打开文件时。作为进一步说明:
\u test\u raise\u exception
回调中显示的
fileObject
参数是的一个实例。您可以使用它的方法解析到磁盘上的文件路径,并检查它是否存在。Do不要依赖于
MFileObject.exists()
方法,因为它似乎总是返回True。