Starting from my last post I’d like to show you how I use Python modules in XSI instead of normal self installing plugins.
You know that XSI automatically recognizes plugins when a proper file is putted under a folder like this: [workgroup or user]\Application\Plugins. We don’t need to specify anything else. Very clever and very useful especially for sharing plugins with all your colleagues.
You also know that Python can find modules and other Python scripts when they are in the same path as the file which is importing them or in a folder specified in the pythonpath. This means that if we set the pythonpath from within XSI and add to it some specific folders from our workgroups, we’ll be able to import Python files or modules in XSI (if it is connected with the workgroups) in every computer in our company, just like the XSI plugins do.
The First Step: Create An OnStartup Event
The first thing we need is create an event, a siOnStartup event, and set properly the pythonpath when XSI start.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
# Purpose: # Scanning all the Workgroups installed and put in the Python Path all the ...\Application\Plugins\PythonModules folders we will find. import win32com.client from win32com.client import constants null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "Daniele Niero" in_reg.Name = "Set Python Path Plug-in" in_reg.Email = "" in_reg.URL = "" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterEvent("SetPythonPath", constants.siOnStartup) #RegistrationInsertionPoint - do not remove this line return true def XSIUnloadPlugin( in_reg ): return true def SetPythonPath_OnEvent( ctxt ): import sys wkgrLocations = Application.WorkGroups; for wkgr in wkgrLocations: workgroupLibFolder = XSIUtils.BuildPath( wkgr, "Application\\Plugins\\PythonModules" ) if workgroupLibFolder not in sys.path : sys.path.append( workgroupLibFolder ) userLocation = Application.InstallationPath( constants.siUserPath ) userLibFolder = XSIUtils.BuildPath(userLocation, "Application\\Plugins\\PythonModules" ) if userLibFolder not in sys.path : sys.path.append( userLibFolder ) Application.LogMessage( sys.path, constants.siVerbose ) # Return value is ignored as this event can not be aborted. return true
So, what did we do exactly? We have just scanned all the workgroups installed (and the user folder as well), built a path like this WorkGroup\Application\Plugins\PythonModules and appended it to the pythonpath list.
The good thing is that all the paths added to the sys.path will be removed when XSI is closed. Helping us to keep the pythonpath clean.
At this point, if we have a PythonModules folder in the Plugins folder in one of the workgroups connected with XSI, we are able to just import every file or modules saved in this PythonModules folder. Since in your company everyone have the workgroups correctly connected, they are able to import a python file or module written by someone else, without specifying or doing anything, just like standard XSI plugins!
The first test and utility python file
The first test we can do is create a file that exposes, once imported, some common and useful stuff we need when we use Python in XSI.
This file could be something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import win32com as win import win32com.server as winServer from win32com.client import constants from win32com.client.dynamic import Dispatch from win32com.client import Dispatch as ComObject from win32com.server.util import wrap App = Dispatch( 'XSI.Application' ).Application XSIFactory = Dispatch( 'XSI.Factory' ) XSIMath = Dispatch( 'XSI.Math' ) null = None false = 0 true = 1
Save it as MyGlobals.py and put it in a PythonModules folder. Open XSI and just test if everything work writing just this few lines in the script editor:
1 2 3 4
from MyGlobals import * App.LogMessage("note that App works, it is a global variable now!") anXSICollection = ComObject("XSI.Collection")
If you don’t have errors form this simple testing code it means we are ready to move on the next step and create a complete class that can help us to handle a GenericProperty.