New in the Softimage 2011 Subscription Advantage Pack
The siutils Python module makes it easier to import modules into your self-installing plugins. Just put your modules in the same location as your plugin file , and you can use the __sipath__ variable to specify the module location.
__sipath__ is always defined in the plugin namespace, so no matter where you put a plugin, you can simply use __sipath__ to specify the location.
Here’s a simple example that shows how to import a module into your plugin.
- Line 04: Import the siutils module
- Line 39: Use add_to_syspath() to add __sipath__ to the Python sys path.
If the module was located in a subfolder of the plugin location, you could use siutils.add_subfolder_to_syspath( __sipath__, ‘mysubfolder’ ) - Line 40: Import the module
import win32com.client from win32com.client import constants import siutils null = None false = 0 true = 1 def XSILoadPlugin( in_reg ): in_reg.Author = "blairs" in_reg.Name = "TestPlugin" in_reg.Major = 1 in_reg.Minor = 0 in_reg.RegisterCommand("Test","Test") #RegistrationInsertionPoint - do not remove this line return true def XSIUnloadPlugin( in_reg ): strPluginName = in_reg.Name Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose) return true def Test_Init( in_ctxt ): oCmd = in_ctxt.Source oCmd.Description = "" oCmd.ReturnValue = true return true def Test_Execute( ): Application.LogMessage("Test_Execute called",constants.siVerbose) # print __sipath__ siutils.add_to_syspath( __sipath__ ) import TestModule TestModule.test( "hello world" ) return true
Pingback: New SDK stuff in the Subscription Advantage Pack « eX-SI Support
What’s the correct way to *not* have to use “import” atop each custom command that needs a particular custom module? I noticed __sipath__ is not set all the time the global scope of the plugin file is executed. Sometimes it’s empty/missing. 😦
Sorry, I’m not sure I understand the question. What do you mean by “atop each custom command” ?
I tried to repro, but I didn’t. But I spent only 5 minutes loading and unloading the plugin and calling the command…does it take longer for the problem to manifest itself?
My bug was something that was happening to me a long time ago in Windows on 2011 or 2012 and at the time __sipath__ was being set sometimes and other times it was blank, messing up my appending to the PATH and therefore importing my custom module.
I’m on 2012 on Linux now and I tried __sipath__ again and it seems to work OK. Sorry for the noise. Maybe it’s been fixed. (I’ll check on Windows at home later.)
Oh, and for clarity sake, by “atop each custom command” I meant that in your sample you do the import at the function scope not in the global scope. When you do that the import is not registered globally, which would imply you would do an import statement on each custom command using that custom module. That seemed silly and redundant, and it is, because if __sipath__ is working as advertised you can do the import outside, first thing in your file and use it later in any functions you wish.
I take it back… It DOES fail sometimes:
# ERROR : Traceback (most recent call last):
# File “”, line 16, in
# PLUGIN_PATH = __sipath__
# NameError: name ‘__sipath__’ is not defined
# – [line 16 in myconfidentialfile.py]
# ERROR : Property Page Script Logic Error (Python ActiveX Scripting Engine)
# ERROR : [14]
# ERROR : [15] PLUGIN_NAME = ‘someName’
# ERROR : >[16] PLUGIN_PATH = __sipath__
# ERROR : [17] if PLUGIN_PATH not in sys.path:
# ERROR : [18] siutils.add_to_syspath( __sipath__ )
# ERROR : [19] import mymodule
# ERROR : Traceback (most recent call last):
# File “”, line 16, in
# PLUGIN_PATH = __sipath__
# NameError: name ‘__sipath__’ is not defined
#
I can’t send you the addon though, but if it helps… I got that error when opening a custom property in the scene, which triggered the PPG’s _DefineLayout() which triggered its _OnInit() which had a PPG.Refresh() in it. Not sure if it’s related.
Maybe PPG logic code doesn’t “see” __sipath__?
PPGLogic could be a problem…usually it is executed its own instance of the scripting engine, and doesn’t see things (like functions) defined in the global scope. I don’t remember if I tested with modules.
Woo! I can repro. 🙂
Don’t know how to paste code here so I put it at http://pastebin.com/tHgTrxCS
Load that plugin. It will load without errors, but then try to select something and create the “fooProperty” by invoking its creation from the Plugin Manager. When it pops up, you will get an __sipath__ not set error.
Tell me if it repros for you.
This workaround works for the PPG logic erroring:
PLUGIN_NAME = ‘TestCmdPlugin’
try:
pluginpath = __sipath__
except:
pluginpath = Application.Plugins(PLUGIN_NAME).OriginPath
if pluginpath not in sys.path:
sys.path.append(pluginpath)
import TestModule