This is how I managed to get it submitting in batches, not sure if the best way.
import Gaffer
import GafferDispatch
import IECore
import imath
Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 1, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 5, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 14, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 0, persistent=False )
__children = {}
__children["Batch_Dispatcher"] = Gaffer.Box( "Batch_Dispatcher" )
parent.addChild( __children["Batch_Dispatcher"] )
__children["Batch_Dispatcher"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.IntPlug( "frameStart", defaultValue = 0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.StringPlug( "frameEnd", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.StringPlug( "batchSize", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( GafferDispatch.LocalDispatcher( "LocalDispatcher" ) )
__children["Batch_Dispatcher"]["LocalDispatcher"]["tasks"].resize( 2 )
__children["Batch_Dispatcher"]["LocalDispatcher"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.StringPlug( "submit", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.StringVectorDataPlug( "batches", defaultValue = IECore.StringVectorData( [ ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.BoxIn( "BoxIn" ) )
__children["Batch_Dispatcher"]["BoxIn"].setup( GafferDispatch.TaskNode.TaskPlug( "out", ) )
__children["Batch_Dispatcher"]["BoxIn"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( GafferDispatch.TaskNode.TaskPlug( "in", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"].addChild( Gaffer.Expression( "Expression1" ) )
__children["Batch_Dispatcher"]["Expression1"]["__in"].addChild( Gaffer.StringPlug( "p0", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"]["Expression1"]["__in"].addChild( Gaffer.StringPlug( "p1", defaultValue = '', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"]["Expression1"]["__in"].addChild( Gaffer.IntPlug( "p2", defaultValue = 0, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"]["Expression1"]["__out"].addChild( Gaffer.BoolPlug( "p0", direction = Gaffer.Plug.Direction.Out, defaultValue = False, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"]["Expression1"]["__out"].addChild( Gaffer.StringVectorDataPlug( "p1", direction = Gaffer.Plug.Direction.Out, defaultValue = IECore.StringVectorData( [ ] ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Batch_Dispatcher"]["Expression1"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["PythonCommand1"] = GafferDispatch.PythonCommand( "PythonCommand1" )
parent.addChild( __children["PythonCommand1"] )
__children["PythonCommand1"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"], 'noduleLayout:customGadget:addButtonTop:visible', False )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"], 'noduleLayout:customGadget:addButtonBottom:visible', False )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"], 'noduleLayout:customGadget:addButtonLeft:visible', False )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"], 'noduleLayout:customGadget:addButtonRight:visible', False )
__children["Batch_Dispatcher"]["__uiPosition"].setValue( imath.V2f( 82.0809479, -66.6898727 ) )
__children["Batch_Dispatcher"]["frameStart"].setValue( 1001 )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["frameStart"], 'nodule:type', '' )
__children["Batch_Dispatcher"]["frameEnd"].setValue( '1036' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["frameEnd"], 'nodule:type', '' )
__children["Batch_Dispatcher"]["batchSize"].setValue( '10' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["batchSize"], 'nodule:type', '' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["dispatcher"]["deadline"]["pool"].setValue( 'none' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["dispatcher"]["deadline"]["secondaryPool"].setValue( 'none' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["dispatcher"]["deadline"]["group"].setValue( 'none' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["tasks"][0].setInput( __children["Batch_Dispatcher"]["BoxIn"]["out"] )
__children["Batch_Dispatcher"]["LocalDispatcher"]["jobName"].setValue( '${script:name}' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["jobsDirectory"].setValue( '${project:rootDirectory}/dispatcher/local' )
__children["Batch_Dispatcher"]["LocalDispatcher"]["executeInBackground"].setValue( True )
__children["Batch_Dispatcher"]["LocalDispatcher"]["ignoreScriptLoadErrors"].setInput( __children["Batch_Dispatcher"]["Expression1"]["__out"]["p0"] )
__children["Batch_Dispatcher"]["LocalDispatcher"]["__uiPosition"].setValue( imath.V2f( -37.1999931, 5.89999866 ) )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["submit"], 'nodule:type', '' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["submit"], 'plugValueWidget:type', 'GafferUI.ButtonPlugValueWidget' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["submit"], 'buttonPlugValueWidget:clicked', 'import GafferDispatch\n#import os,re,ast\nimport GafferUI\n\ndef generate_ranges(start, end, batch_size):\n return [f"{i}-{min(i+batch_size-1, end)}" for i in range(start, end+1, batch_size)]\n \nnode = plug.node()\nscriptWindow = button.ancestor( GafferUI.ScriptWindow )\t\nroot = scriptWindow.scriptNode()\nscriptName = root.context()["script:name"]\n\nframeStart = node[\'frameStart\'].getValue()\nframeEnd = node[\'frameEnd\'].getValue()\nbatchSize = node[\'batchSize\'].getValue()\n\n#### DISPATCHER\nranges = generate_ranges(int(frameStart),int(frameEnd),int(batchSize))\n\nfor range in ranges:\n\tdispatcher = GafferDispatch.LocalDispatcher()\n\tdispatcher["framesMode"].setValue( dispatcher.FramesMode.CustomRange )\n\t\n\tdispatcher["jobName"].setValue(scriptName+str(range))\n\n\tdispatcher["frameRange"].setValue(range)\n\t# Uncomment to tell dispatcher where to put temporary files used during dipatch.\n\t#dispatcher["jobsDirectory"].setValue( "/tmp" )\n\tdispatcher["executeInBackground"].setValue(True)\n\n\t#dispatcher.dispatch([ node["FrameMask"] ])\n\tdispatcher.dispatch([ node["LocalDispatcher"] ])\n\n\t' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["submit"], 'label', 'SUBMIT' )
__children["Batch_Dispatcher"]["batches"].setInput( __children["Batch_Dispatcher"]["Expression1"]["__out"]["p1"] )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["batches"], 'nodule:type', '' )
__children["Batch_Dispatcher"]["BoxIn"]["__in"].setInput( __children["Batch_Dispatcher"]["in"] )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["BoxIn"]["__in"], 'description', 'Output connections to downstream nodes which must\nnot be executed until after this node.' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["BoxIn"]["__in"], 'plugValueWidget:type', '' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["BoxIn"]["__in"], 'nodule:type', 'GafferUI::StandardNodule' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["BoxIn"]["out"], 'noduleLayout:section', 'bottom' )
__children["Batch_Dispatcher"]["BoxIn"]["__uiPosition"].setValue( imath.V2f( -37.8999939, 19.8000011 ) )
__children["Batch_Dispatcher"]["in"].setInput( __children["PythonCommand1"]["task"] )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["in"], 'description', 'Output connections to downstream nodes which must\nnot be executed until after this node.' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["in"], 'plugValueWidget:type', '' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["in"], 'nodule:type', 'GafferUI::StandardNodule' )
Gaffer.Metadata.registerValue( __children["Batch_Dispatcher"]["in"], 'noduleLayout:section', 'top' )
__children["Batch_Dispatcher"]["Expression1"]["__in"]["p0"].setInput( __children["Batch_Dispatcher"]["batchSize"] )
__children["Batch_Dispatcher"]["Expression1"]["__in"]["p1"].setInput( __children["Batch_Dispatcher"]["frameEnd"] )
__children["Batch_Dispatcher"]["Expression1"]["__in"]["p2"].setInput( __children["Batch_Dispatcher"]["frameStart"] )
__children["Batch_Dispatcher"]["Expression1"]["__uiPosition"].setValue( imath.V2f( -28.8236771, 11.8008223 ) )
__children["PythonCommand1"]["dispatcher"]["deadline"]["pool"].setValue( 'none' )
__children["PythonCommand1"]["dispatcher"]["deadline"]["secondaryPool"].setValue( 'none' )
__children["PythonCommand1"]["dispatcher"]["deadline"]["group"].setValue( 'none' )
__children["PythonCommand1"]["command"].setValue( '\nfor frame in frames:\n\tprint(frame)\n\n\n' )
__children["PythonCommand1"]["framesMode"].setValue( 2 )
__children["PythonCommand1"]["__uiPosition"].setValue( imath.V2f( 82.0809479, -56.6655922 ) )
__children["Batch_Dispatcher"]["Expression1"]["__engine"].setValue( 'python' )
__children["Batch_Dispatcher"]["Expression1"]["__expression"].setValue( 'parent["__out"]["p0"] = False\n\ndef generate_ranges(start, end, batch_size):\n return [f"{i}-{min(i+batch_size-1, end)}" for i in range(start, end+1, batch_size)]\n \nframeStart = parent["__in"]["p2"]\nframeEnd = parent["__in"]["p1"]\nbatchSize = parent["__in"]["p0"]\n\nranges = generate_ranges(int(frameStart),int(frameEnd),int(batchSize))\n\nparent["__out"]["p1"] = IECore.StringVectorData( ranges )' )
del __children