time.sleep,允许父应用程序仍然评估?

时间:2013-11-20 20:58:07

标签: python maya

我在为Maya和Houdini编写脚本时遇到了很多情况,我需要等待GUI的各个方面更新才能调用其余的Python代码。我在考虑在两种情况下调用time.sleep会解决我的问题,但似乎time.sleep也支持父应用程序。这意味着无论睡眠是否存在,我的脚本都会对其进行完全相同的评估,它只会暂停一段时间。

我想在Python中的一个单独的线程中运行我的脚本,看看是否会释放应用程序在睡眠期间仍然运行,但我还没来得及测试它。

我想在此期间我会问是否有人知道这种情况的其他解决方案。

2 个答案:

答案 0 :(得分:1)

Maya - 或者更准确地说是Maya Python - 并不是真正的多线程(Python本身有一种狡猾的多线程,因为所有线程都在争夺恐惧global interpreter lock,但这不是你的问题)。您可以使用线程模块在Maya中正常运行线程代码;尝试:

import time
import threading
def test():
   for n in range (0, 10):
       print "hello"
       time.sleep(1)
 t = threading.Thread(target = test)
 t.start()

这将以一秒的间隔向你的听众打印'hello'10次,而不会关闭交互性。

不幸的是,maya的许多部分 - 包括最着名的所有用户创建的UI和大多数场景操作 - 只能从“主”线程运行 - 拥有maya UI的线程。因此,您无法使用上述技术更改窗口中文本框的内容(更糟糕的是,您将获得误导性错误消息 - 当您从侦听器运行它时可以正常运行的代码但是你从线程中调用它并礼貌地返回完全错误的错误代码)。您可以执行诸如网络通信,写入文件或在单独的线程中进行长时间计算等问题 - 但是如果您尝试从线程执行此操作,则UI工作和许多常见场景任务将失败。

Maya在maya.utils模块中有部分解决方法。您可以使用函数executeDeferred和executeInMainThreadWithResult。这些将等待空闲时间运行(例如,如果你正在播放动画,它们将不会运行),然后就像你在主线程中完成它们一样。 maya docs的例子给出了这个想法:

import maya.utils import maya.cmds
def doSphere( radius ):
    maya.cmds.sphere( radius=radius )
maya.utils.executeInMainThreadWithResult( doSphere, 5.0 )

这可以帮助您获得所需的大部分内容,但您需要仔细考虑如何将您的任务分解为线程友好的块。当然,运行线程程序总是比单线程程序更难,你需要设计代码,以便在你工作时另一个线程与变量混淆时事情不会破坏。好的并行编程是一大堆鱼,虽然归结为几个基本的想法:

1)在需要时使用RLocks建立对对象(对于短操作)的独占控制 2)将共享数据放入安全容器中,例如@dylan的Queue中的Queue 3)要清楚哪些对象是可共享的(它们应该很少!),哪些不是

这是decent (long) overview.

至于Houdini,我不确定,但是this article听起来像是出现了类似的问题。

答案 1 :(得分:0)

更好的解决方案,而不是睡眠,是一个while循环。设置while循环以检查共享值(甚至是像Queue这样的线程安全结构)。你等待的父进程可以完成他们的工作(或者是孩子,产生什么并不重要),当他们完成工作时,他们会向Queue /变量发送一个true / false / 0/1 /,让其他进程知道他们可以继续。