Nuke Python run the same script / node multiple times without scriptOpen and scriptClose?

1.5k views Asked by At

I've got a python script for (Foundry) Nuke that listens to commands and for every command received executes a Write node. I've noticed that if I don't do nuke.scriptOpen(my_renderScript) before nuke.execute(writeNode,1,1) and then after do nuke.scriptClose(my_renderScript), then the write command seems to execute but nothing is written to file, despite me changing knob values before I call execute again.

The reason I want to not use scriptOpen and scriptClose every time I execute -the same node- is for performance. I'm new to nuke, so correct me if I'm wrong, but it's inefficient to unload and reload a script every time you want to run a node inside it, right?

[EDIT] Here's a simple test script. Waits for command line input and runs the function, then repeats. If I move the script open and script close outside the looping / recursive function, then it will only write to file once, the first time. On subsequent commands it will "run", and nuke will output "Total render time: " in the console (render time will be 10x faster since it's not writing / doing anything) and pretend it succeeded.

# Nuke12.2.exe -nukex -i -t my_nukePython.py render.nk
# Then it asks for user input. The input should be:
# "0,1,0,1", "1024x1024", "C:/0000.exr", "C:/Output/", "myOutput####.png", 1, 1
# then just keep spamming it and see.

import nuke
import os
import sys
import colorsys

renderScript = sys.argv[1]
nuke.scriptOpen(renderScript)

readNode = nuke.toNode("Read1")
gradeNode = nuke.toNode("CustomGroup1")
writeNode = nuke.toNode("Write1")


def runRenderCommand():
    cmdArgs = input("enter render command: ")
    
    print cmdArgs
    
    if len(cmdArgs) != 7:
        print "Computer says no. Try again."
        runRenderCommand()
    
    nuke.scriptOpen(renderScript)
    
    colorArr = cmdArgs[0].split(",")

    imageProcessingRGB = [float(colorArr[0]), float(colorArr[1]), float(colorArr[2]), float(colorArr[3])]
    previewImageSize = cmdArgs[1]
    inputFileLocation = cmdArgs[2]
    outputFileLocation = cmdArgs[3]
    outputFileName = cmdArgs[4]
    startFrameToExecute = cmdArgs[5]
    endFrameToExecute = cmdArgs[6]

    readNode.knob("file").setValue(inputFileLocation)
        
    writeNode.knob("file").setValue(outputFileLocation+outputFileName)

    gradeNode.knob("white").setValue(imageProcessingRGB)
    print gradeNode.knob("white").getValue()

    nuke.execute(writeNode.name(),20,20,1)
    runRenderCommand()
    
    nuke.scriptClose(renderScript)
    
runRenderCommand()
1

There are 1 answers

5
Spectraljump On

The problem was between the chair and the screen. Turns out my example works. My actual code that I didn't include for the example, was a bit more complex and involved websockets.

But anyway, it turns out I don't know how python scoping sintax works ^__^ I was making exactly this error in understanding how the global keyword should be used: referenced before assignment error in python

So now it indeed works without opening and closing the nuke file every time. Funny how local scope declaration in python in this case in my code made it look like there's no errors at all... This is why nothing's sacred in scripting languages :)

Is there a way to delete this question on grounds that the problem turns out was completely unrelated to the question?

Well that took an unexpected turn. So yes I had the global problem. BUT ALSO I WAS RIGHT in my original question! Turns out depending on the nodes you're running, nuke can think that nothing has changed (probably the internal hash doesn't change) and therefore it doesn't need to execute the write command. In my case I was giving it new parameters, but the parameters were the same (telling it to render the same frame again)

If I add this global counter to the write node frame count (even though the source image only has 1 frame), then it works.

nuke.execute(m_writeNode.name(),startFrameToExecute+m_count,endFrameToExecute+m_count, continueOnError = False)
m_count+=1

So I gotta figure out how to make it render the write node without changing frames, as later on I might want to use actual frames not just bogus count increments.