【问题标题】:How to cancel an execution of Write node in Nuke?如何取消 Nuke 中写入节点的执行?
【发布时间】:2022-01-10 02:39:08
【问题描述】:

我一直在用 Python 编写 Nuke 渲染管理器,但遇到了一个问题: nuke.cancel() 似乎无法正常工作。 我的 python 脚本创建一个主类并连接到一个服务器(用 Java 编写),然后进入一个无限循环,每次都获得一个新任务(以 JSON 对象的形式)。它得到的每个循环都会打开一个脚本?找到写入节点并执行它们。为了向服务器报告进度,我添加了回调: nuke.addBeforeFrameRender(lambda: self._pre_frame_render())nuke.addAfterFrameRender(lambda: self._post_frame_render()) 在哪里

def _pre_frame_render(self):
    self._host_socket.send(struct.pack('>b', 1))
    self._host_socket.send(struct.pack('>i', nuke.frame()))

def _post_frame_render(self):
    self._host_socket.send(struct.pack('>b', 2))
    self._host_socket.send(struct.pack('>i', nuke.frame()))

为了在服务器上启用cancel 方法,我有一个单独的线程在渲染处于活动状态时运行并等待“取消”请求

class CancelHandler(threading.Thread):
    def __init__(self, input_socket, cancel_callback):
        threading.Thread.__init__(self)
        self.cancel_set = threading.Event()
        self.run_set = threading.Event()
        self._input_socket = input_socket
        self._cancel_callback = cancel_callback

    def run(self):
        while True:
            if self.run_set.is_set():
                msg_raw = recv_msg(self._input_socket)
                msg = json.loads(msg_raw)
                if 'mode' in msg and msg['mode'] == 'cancel':
                    print msg_raw
                    self.cancel_set.set()
                    self.run_set.clear()
                    self._cancel_callback()

cancel_callback 定义为

def _cancel_callback(self):
        nuke.cancel()
        self._is_canceled = True

在循环开始之前,我启动CancelHandler 线程,并在每次迭代中设置run_set 操作,然后清除以让主线程进行通信。在这之间的不同阶段,我检查是否设置了cancel_set,以防“取消”请求到达。

除了一件事之外,以上所有似乎都可以正常工作:nuke.execute() 完全没有做任何事情 - 渲染只是继续。我已经尝试将它放在nuke.addBeforeFrameRendernuke.addAfterFrameRender 回调中,但这无济于事。另外我认为它可能在错误的线程中执行,所以我尝试了nuke.executeInMainThread(nuke.cancel),但没有成功。

documentation 内容如下:

execute(nameOrNode, start, end, incr, views, continueOnError= False) ... 如果 Nuke 在 GUI 上运行,这将弹出一个进度表。如果用户点击取消按钮,此命令将返回“已取消”错误。 如果 Nuke 从 nuke 命令行运行(即 nuke 是使用 -t 开关启动的),execute() 会在执行过程中打印一个文本百分比。 如果用户键入 ^C,它将中止 execute() 并返回“已取消”错误。

所以我尝试用os.kill(os.getpid(), signal.CTRL_C_EVENT) 替换nuke.cancel() 这实际上停止了渲染,但 execute() 从未返回,因此脚本无法继续

既然execute()应该

返回一个“取消”错误

我试图从execute()os.kill(os.getpid(), signal.CTRL_C_EVENT) 代码中捕获nuke.CancelledError 异常,但它没有被抛出。

奇怪的是,当我运行这个回调时:

def _cancel_callback(self):
        self._is_canceled = True
        os.kill(os.getpid(), signal.CTRL_C_EVENT)
        print "Cancelled"

print 行被执行

我对 python 还很陌生,所以这可能是菜鸟的错误,但有谁知道我可能做错了什么,或者它是否是 API 中的错误? 或者也许有人会提出更好的解决方案来解决这个问题 - 将不胜感激!

到目前为止,我看到的唯一摆脱这种情况的方法是简单地关闭工作进程,然后启动一个新进程,但每次有人想取消工作时,这样做是一件很丑陋的事情。

使用 Nuke 9.0v3 完整的源代码可以在PYTHON目录下的https://bitbucket.org/andrey_glebov/nukerendermanager/src找到

【问题讨论】:

  • 好问题,我希望我知道答案。不是答案,但您可以考虑使用像 Rush 这样的渲染队列系统,它适用于大多数软件。它(和其他类似的)的工作方式是每次都通过干净的命令行渲染。 Nuke 命令行渲染器会在几秒钟内启动,因此尝试在渲染之间保持活跃可能不值得。
  • 是的,对于渲染来说,代价并不大,但我的任务包括批量创建具有指定节点的脚本(主要用于转码处理,如高质量的高分辨率或降噪处理),以及那些可能需要不到一秒钟。如果找不到可行的解决方案,我只会在需要取消渲染时终止进程。
  • 我建议写信给 The Foundry。这听起来确实像一个错误,而且他们通常对这些反应非常敏感。如果您找到解决方案,请随时在此处“回答您自己的问题”以帮助未来的访问者。

标签: python multithreading nuke


【解决方案1】:

以下命令取消了Progress 窗口,因此它也停止了渲染过程。

nuke.toNode('Write1')['disable'].setValue(1)

【讨论】:

    猜你喜欢
    • 2016-04-10
    • 2018-03-19
    • 1970-01-01
    • 2019-11-16
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    相关资源
    最近更新 更多