AWS Thinkbox Discussion Forums

Event Plugin calling Nuke

Hi,
I am trying to script event plugin for rendering Quicktimes after Nuke job with Deadline 8. Unfortunately, Draft doesn’t seem to have functionality I need (mostly metadata handling), so I decided to spawn another Nuke script for Quicktime creation.

Is there a recommended way how to import module nuke in the event plugin?

What is the best way to stop the event to propagate, so I do not try to create quicktime from quicktime from quicktime…

Thank you !

Here is my code so far…

[code]import re, os

from System.IO import *
from System.Text import *

from Deadline.Events import *
from Deadline.Scripting import *

######################################################################

This is the function that Deadline calls to get an instance of the

main DeadlineEventListener class.

######################################################################
def GetDeadlineEventListener():
return MyEvent()

def CleanupDeadlineEventListener( eventListener ):
eventListener.Cleanup()

######################################################################

This is the main DeadlineEventListener class for MyEvent.

######################################################################
class MyEvent (DeadlineEventListener):

def __init__( self ):
	self.OnJobFinishedCallback += self.OnJobFinished
	
def Cleanup( self ):
	del self.OnJobFinishedCallback

def OnJobFinished( self, job ):
	
	# Only submit a dailies job for finished Nuke jobs
	if job.JobPlugin != "Nuke":
		return None
	else:
		# output filenames
		outputDirectories = job.JobOutputDirectories
		outputFilenames = job.JobOutputFileNames
		if len( outputFilenames ) == 0:
			self.LogInfo( "ERROR: Could not find a full output path in Job properties; No Draft job will be created." )
			
		# frame range
		frames = []
		for frame in job.Frames:
			frames.append(frame)
		sortedInputFrameList = sorted(frames)
		inputFrameList = FrameUtils.ToFrameString(frames) # not sure what is this for...
		
		try:
			first = int(sortedInputFrameList[0])
			last = int(sortedInputFrameList[-1])
		except:
			first = 0
			last = 0
		framesList = str(first) + ' - ' + str(last)
		self.LogInfo( "Dailies render range: " + framesList)

		# for every nuke output (writer)
		for i in range(len(outputDirectories)):
			outputFullPath = ( ('%s/%s') % (outputDirectories[i], outputFilenames[i]))
			outputFullPath = self.replaceCounterSign(outputFullPath, 0).replace('\\', '/')		# the  replace // can be problem in paths with server names...
			self.LogInfo( "Output sequence %d : %s" % (i, outputFullPath))
			
			_scriptname = outputDirectories[i] + '/' + outputFilenames[i] + '_NukeDailies.nk'
			self.LogInfo( "_scriptname: " + _scriptname)
			
			"""
			import nuke
			
			nuke.scriptNew()
			nuke.scriptSave(_scriptname)
			
			_filepath = outputDirectories[i] + '/' + outputFilenames[i]
			self.LogInfo( "_filepath: " + _filepath)
			r = nuke.createNode('Read', 'file ' + _filepath)
			r.knob('first').setValue(first)
			r.knob('last').setValue(last)
			r.knob('origfirst').setValue(first)
			r.knob('origlast').setValue(last)
			
			nuke.scriptSave(_scriptname)
			"""
			
			# create job info file
			jobInfoFilename = Path.Combine(ClientUtils.GetDeadlineTempPath(), "nuke_job_info.job")
			writer = StreamWriter(jobInfoFilename, False, Encoding.Unicode)
			writer.WriteLine("Plugin=Nuke")
			writer.WriteLine("Name=NukeDailies")
			writer.WriteLine("Comment=Autosubmitted after Nuke job...")
			writer.WriteLine("Frames=%s" % job.JobFrames) 
			writer.Close()
			
			# create plugin info file
			_scriptname = "Z:/rendertest/rendertest_A.nk"
			pluginInfoFilename = Path.Combine(ClientUtils.GetDeadlineTempPath(), "nuke_plugin_info.job" )
			writer = StreamWriter(pluginInfoFilename, False, Encoding.Unicode)
			writer.WriteLine("SceneFile=%s" % _scriptname)
			writer.WriteLine("Version=10") # nuke version
			writer.Close()
			
			# submit nuke script
			exitCode = ClientUtils.ExecuteCommand( (jobInfoFilename, pluginInfoFilename) )
			
		
def replaceCounterSign(self, path, mode, extraStringBeforeCounter = ''):
	''' Replaces counter-like string in path with other type of counterstring. Known counters: %04d (printf notation), multiple #s, multiple ?s. Optionally can insert custom string before the counter.'''

	if re.search('#+', path):
		counterString = re.search('#+', path).group()
		counterLength =  len(counterString)
	
	elif re.search('\?+', path):
		counterString = re.search('\?+', path).group()
		counterLength =  len(counterString)
	
	elif re.search('%0\dd+', path):
		counterString = re.search('%0\dd', path).group()
		counterLength =  int(counterString.replace('%0', '').replace('d', ''))
	
	if mode == 0:								# gives back printf notation
		newCounter = '%%0%dd' % counterLength
	elif mode == 1:								# gives back multiple # signs
		newCounter = ('#'* counterLength)
	elif mode == 2:								# gives back multiple ? signs
		newCounter = ('?'* counterLength)
	elif mode == 3:								# replaces counter with empty string
		newCounter  = ''						
	
	newCounter = extraStringBeforeCounter + newCounter	# inserting extra string before the counter
	
	replacedPath = path.replace(counterString, newCounter)
	return replacedPath	

[/code]

For the propagation, you can use a sentinel value stored in the ExtraInfoKeyValue area of a job object. If “CreatedBy=QuicktimeScript” or something similar is seen, you could stop the loop there.

As far as using external packages, you can define new search paths in the Repository options here:
docs.thinkboxsoftware.com/produc … n-settings

Hi eamsler,
Thank you for help. As for using Nuke as external package, it looks like it is quite complicated and I should maybe use this:
github.com/Nvizible/NukeExternalControl

Can you please tell me how do I read SceneFile (nuke script that triggered the event I am trying to catch)? It should be in plugin info but I can’t figure out the syntax needed. Sorry for that, I am just Nuke artist fighting with Python…

Thank you,
Jirka

Hi Jirka,

You should not need to use the NukeExternal control, nuke is perfectly capable of launching python scripts that are make to automate various areas of nuke.
if you run a nuke job with batch mode turned off and supply a .py file instead of a .nk .
When deadline goes to execute nuke, its running: nuke -x /path/to/file.py

We have a similar process that generates a not so simple slap comp that is generated in nuke and then rendered to a mov.

Hope this helps.
Kym

Awesome! Thank you kwatts, that is very helpful.

If someone needs it, Nuke scene file can be read in event plugin simply by:

sceneFile = job.GetJobPluginInfoKeyValue('SceneFile')

Now I am trying to pass some info (like nuke frame rate) to my event plugin. I do not want to mess with Nuke submission script, so I was thinking that (ab)using CustomSanityChecks.py to set initExtraInfo would work, something like:

DeadlineGlobals.initExtraInfo1 = "fps=" + str(nuke.value("root.fps"))

But it doesn’t. What is the good way to pass info from Nuke to Deadline and read it in event plugin? It looks to me that Deadline somehow remembers old CustomSanityChecks.py even if I delete it from repository…

Thanks again,
Jirka

Thanks for the into Kym! You might be seeing the cache saving a copy. The cache couldn’t be turned off until about 8.0 SP4 and is always on when using the Proxy. Things were in flux a bit with the cache actually through 8.0. What version are you on?

As far as passing it to an event, storing it in the extra info is best. I remember us needing to extend some bits form the submitter in the past… Looking at it doesn’t seem to actually write that information anywhere…

I’ll have us fix that up. In the mean time… I think editing the submitter is unavoidable. Try using ExtraInfo9 since we don’t use that in the Nuke submitter anywhere.

Hi Edwin,

I am on 8 (8.0.6.5 Release (b39480ccd)). Maybe time to update…

Can you please give me an example how to store info before submission in CustomSanityChecks.py and access it in event plugin? Is there a way to work with named key=value pairs in CustomSanityChecks.py?

Here is what I tried:
CustomSanityChecks.py:

import DeadlineGlobals
DeadlineGlobals.initExtraInfo0 = "fps=" + str(nuke.value("root.fps"))

event.py:

fps = job.GetJobExtraInfoKeyValue( "[ExtraInfo0]" )

Thank you so much,
Jirka

The sanity check should be fine. In fact, it looks like I may have misread the plugin here. Would you be able to send over your sanity check and I’ll see if I can figure out why it’s not working?

Sure,
Here is my plugin and sanity check file.

Thank you,
Jirka
CustomSanityChecks.zip (317 Bytes)
NukeDailies.zip (11.1 KB)

Hi,
I updated our Deadline to 8.0.11.2, hope it will help with custom sanity checks…

Jirka

Well, I played around with things a bit here and it’s working for my simple test. I’m getting this in my submission params for “Modify Job Properties”:

...
ScheduledStartDateTime=16/11/2016 10:31
ExtraInfo0=fps=24.0
OverrideTaskExtraInfoNames=False
...

Can you make sure that’s coming through for you?

Thank you,
I will be able to check Friday (state holiday here).

Best,
Jirka

Hi again,

I checked several times, and I have to say that CustomSanityChecks.py doesn’t work form me at all after I updated to newest Deadline.
There is nothing like “ExtraInfo0=” in my submission params for “Modify Job Properties”.

I even put the message line in the script that should pop right before submission dialog when I call deadline script, and nothing happens. Please note that this message worked before…

nuke.message( "sanity check" )

Here is my complete path to the script:
\dpn001\Deadline\DeadlineRepository8\submission\Nuke\Main\CustomSanityChecks.py

Is there any way how to check if Deadline is actually executing the script?

Thank you,
Jirka

It does sound like there is something wrong in the submitter itself. I usually go the script editor panel to see how things went. For example, I apparently made a mistake is my sanity checker:

Thanks again, it is working now.

I had the same indentation error and didn’t notice it shows in Nuke script panel. Oh well…

I can successfully read stuff from Nuke in event plugin without the need to modify standard Deadline submission script. Yay!

Thank you for all the help.

Jirka

Welcome sir! Glad I could help.

Privacy | Site terms | Cookie preferences