title: How to cancel an execution of Write node in Nuke?
body: <p>I have been writing a Nuke render manager in Python and came across a problem:
  <code>nuke.cancel()</code> doesn't seem to work right.
  My python script creates a main class and connects to a server (written in Java) and then enters an infinite loop, each time getting a new task (in the form of a JSON object). Each loop it gets opens a script? finds the write nodes and executes them. To report progress back to the server I have added callbacks:
  <code>nuke.addBeforeFrameRender(lambda: self._pre_frame_render())</code>
  and
  <code>nuke.addAfterFrameRender(lambda: self._post_frame_render())</code>
  where</p>
  
  <pre><code>def _pre_frame_render(self):
      self._host_socket.send(struct.pack('&gt;b', 1))
      self._host_socket.send(struct.pack('&gt;i', nuke.frame()))
  
  def _post_frame_render(self):
      self._host_socket.send(struct.pack('&gt;b', 2))
      self._host_socket.send(struct.pack('&gt;i', nuke.frame()))
  </code></pre>
  
  <p>To enable a <code>cancel</code> method on the server, I have a separate thread that runs while the rendering is active and waits for a 'cancel' request</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>The <code>cancel_callback</code> is defined as</p>
  
  <pre><code>def _cancel_callback(self):
          nuke.cancel()
          self._is_canceled = True
  </code></pre>
  
  <p>Before the loop starts I start the <code>CancelHandler</code> thread and on each iteration the <code>run_set</code> action is set, and after - cleared to let the main thread communicate. In between that at different stages I check if <code>cancel_set</code> has been set in case a 'cancel' request has arrived.</p>
  
  <p>All of the above seems to work fine except for one thing: <code>nuke.execute()</code> does absolutely nothing - the render just continues. I have tried putting it in the <code>nuke.addBeforeFrameRender</code> and <code>nuke.addAfterFrameRender</code> callbacks but that does nothing. Also I thought it might be executing in the wrong thread so I tried <code>nuke.executeInMainThread(nuke.cancel)</code> with no luck.</p>
  
  <p>The <a href="http://docs.thefoundry.co.uk/nuke/90/pythonreference/" rel="noreferrer">documentation</a> reads:</p>
  
  <blockquote>
    <p>execute(nameOrNode, start, end, incr, views, continueOnError= False)
    ...
    If Nuke is run with the GUI up, this will pop up a progress meter. If the user hits the cancel button this command will return 'cancelled' error. 
    If Nuke is run from the nuke command line (ie nuke was started with the -t switch) execute() prints a text percentage as it progresses.
    If the user types ^C it will aborting the execute() and return a 'cancelled' error.</p>
  </blockquote>
  
  <p>so I tried replacing <code>nuke.cancel()</code> with <code>os.kill(os.getpid(), signal.CTRL_C_EVENT)</code>
  That actually stopped the render but <code>execute()</code> never returned so the script couldn't continue</p>
  
  <p>Since <code>execute()</code> should</p>
  
  <blockquote>
    <p>return a 'cancelled' error</p>
  </blockquote>
  
  <p>I tried to catch the <code>nuke.CancelledError</code> exception both from the <code>execute()</code> and the <code>os.kill(os.getpid(), signal.CTRL_C_EVENT)</code> code but it wasn't thrown.</p>
  
  <p>Curiously, when I ran this callback:</p>
  
  <pre><code>def _cancel_callback(self):
          self._is_canceled = True
          os.kill(os.getpid(), signal.CTRL_C_EVENT)
          print "Cancelled"
  </code></pre>
  
  <p>the <code>print</code> line got executed</p>
  
  <p>I am fairly new to python so it might be a noob's mistake but does anyone know what I might be doing wrong or if it's a bug in the API?
  Or maybe someone cam come up with a better solution to the problem - that would be greatly appreciated!</p>
  
  <p>So far the only way out of this situation I see is to simply shut down the worker process and then launch a new one, but that would be kind of an ugly thing to do each time someone wants to cancel a job.</p>
  
  <p>Using Nuke 9.0v3
  Full source code can be found at <a href="https://bitbucket.org/andrey_glebov/nukerendermanager/src" rel="noreferrer">https://bitbucket.org/andrey_glebov/nukerendermanager/src</a> in PYTHON directory</p>