Lua vs Python scripts

The way Lua and Python scripts are handled in CoppeliaSim (next to differences related to the language itself) displays small differences, which are discussed here:

  • Python scripts require a #python header tag as the very first instruction/comment:
  • #python def sysCall_init(): print("Hello world!")
  • Lua code always executes in the same thread as CoppeliaSim and is thus quite fast. Python code on the other hand is launched in a new process, which connects to CoppeliaSim via socket communication. This implies that Python code will usually start and run slower than Lua code.
  • Python scripts are handled via Lua wrapper code, which handles the launch and communication of each Python script. Auxiliary Lua code can be passed via the luaExec command, within a Python comment section. That code must come immediately after the #python header tag:
  • #python #luaExec wrapper='myWrapperCode' -- looks for myWrapperCode.lua in Lua's search path #luaExec additionalPaths={'c:/path1','c:/path2'} -- adds additional Python module search paths #luaExec additionalIncludePaths={'c:/Python38','c:/path2'} -- adds additional paths to search for the include file '''luaExec function myLuaFunction() -- do something here end ''' def sysCall_init(): print("Hello world!")
  • The import directive does not work when importing the primary Python file, and following should be used instead:
  • #python include myExternalFile # myExternalFile is the pythonScript name or path (absolute or relative), without quotes nor the ending '.py' # searched paths include: # <CoppeliaSim executable path>/ # <CoppeliaSim executable path>/python # <current scene path>/ # <additional path>/ (see system/usrset.txt and value 'additionalPythonPath') # additional include paths passed via #luaExec additionalIncludePaths={'c:/Python38'}
  • Threaded Lua code, since implemented via coroutines, will always block while executing (i.e. CoppeliaSim won't handle any other task during that time). This is most of the time not noticeable, except when calling blocking functions that are foreign to CoppeliaSim. Threaded Python code on the other hand, will never block when executing, also with functions that are foreign to CoppeliaSim.
  • Python threaded scripts do not have an initialization nor clean-up callback. They should thus handle initialization and clean-up within their sysCall_thread function:
  • #python def sysCall_thread(): sim.setThreadAutomaticSwitch(True) # Do some initialization here, e.g.: h = sim.getObject('/myCube') originalColor = sim.getObjectColor(h,0,sim.colorcomponent_ambient_diffuse) sim.setObjectColor(h,0,sim.colorcomponent_ambient_diffuse,[1,0,0]) # Handle the main loop here, e.g.: while sim.getThreadExistRequest() == False: print(sim.getObjectPosition(h,-1)) # Do some clean-up here: sim.setObjectColor(h,0,sim.colorcomponent_ambient_diffuse,originalColor)
  • Python threaded scripts should explicitly enable thread automatic switching, otherwise CoppeliaSim will block (or wait until sim.switchThread is called):
  • #python def sysCall_thread(): sim.setThreadAutomaticSwitch(True) while sim.getThreadExistRequest() == False: pass
  • Python threaded scripts will need to call a message pump (via sim.handleExtCalls) in order to have user callback functions to be serviced:
  • #python def sysCall_thread(): sim.setThreadAutomaticSwitch(True) xml ='<ui title="Custom UI"> <button text="Click me!" on-click="click_callback"/> </ui>' ui=simUI.create(xml) while sim.getThreadExistRequest() == False: sim.handleExtCalls() simUI.destroy(ui) def click_callback(ui,button): print("button was clicked!")
  • Lua callback functions are always reentrant, while Python callback functions are usually non-reentrant. A workaround to this is to have Lua assist Python like in following example, where Python would call a Lua function:
  • #python '''luaExec function myLuaFunction() print("Hello") end ''' def sysCall_init(): object=sim.getScriptInt32Param(sim.handle_self,sim.scriptintparam_objecthandle) path=sim.getObjectAlias(object,1) sim.callScriptFunction('myLuaFunction@'+path,sim.scripttype_childscript)
  • Some rare API functions will only be availabe in Lua, while other only in Python.
  • The word table in the documentation refers to array-like or map-like items in Lua, while in Python, it refers to either lists or dicts.
  • Finally remember that Python lists have a zero-based numbering, while Lua array-like tables have a 1-based numbering.