Category Archives: Unix

Nuke and Shotgun Integration

molecule-style

In my years at the Molecule in NYC, first as a freelancer and then as a perma-lancer, I had lots of time to observe how a mid-sized studio manages the sometimes huge number of shots that need to be kept track of on a daily basis. When I started, the studio was using Ftrack to manage its shot pipeline, and while poking around online I saw that ftrack had a python API, and a lightbulb went off – Nuke + Python + Ftrack = ? Awesomeness, anyway.

So I went to work on building a nuke-based shot tracking system, first for artists but then expanding to include supervisors as well. I called it “the dashboard”, and though it started small it quickly became essential to the Molecule’s pipeline. When the studio switched tracking packages to Shotgun, a lot more functionality was exposed and the whole thing just got 50% better. You can catch a quick glimpse of it in this promotional video from Autodesk – at around 0:55 in this video, the awesome Rick Shick talks about how he uses it instead of the web-based interface almost exclusively in his role as comp supervisor:


Gone were the days of manually creating contact sheets for each project; now every artist and supervisor had access to dynamic contact sheets, through which they could see and change statuses, read and post notes and images, and quickly open any shot.

Terminating a child process from python

fixing a problem with calling 3rd party applications as subprocesses

I’ve been working on improving my renderfarm, and I’ve run into some trouble trying to close clients remotely. You can easily end a python process with sys.exit(), however if a rendering application (say Nuke) has been spawned by the script, it will not close. After some digging (and a bunch of great help from stackOverflow) I seem to have come up with a solution. When you call a 3rd party application with either call() or:

process = Popen(allRenderArg, env=os.environ)

Python will create a tiny, dummy process which only exists to call that application. When you exit your script, python will clean up those dummy processes, but won’t kill child processes, thereby leaving the renders going.

The solution that I’ve come up with is to get the pid of those dummy python processes, then use some unix commands to find the pids of their children, and kill them with os.kill(). If this was a linux platform I could do it in a more efficient way (possibly using pstree) but on OSX I have to use grep and some fancy code:

processId = process.pid
print "attempting to terminate "+str(processId)
command = " ps -o pid,ppid -ax | grep "+str(processId)+" | cut -f 1 -d \" \" | tail -1"
ps_command = Popen(command, shell=True, stdout=PIPE)
ps_output = ps_command.stdout.read()
retcode = ps_command.wait()
assert retcode == 0, "ps command returned %d" % retcode
print "child process pid: "+ str(ps_output)
os.kill(int(ps_output), signal.SIGTERM)
os.kill(int(processId), signal.SIGTERM)

There might be a nicer way, but I don’t know it.