Thursday, 13 February 2014

Python Importing : Import Correct Module Based on Caller

EDIT:
Please view comments below for suggestions doing this in a more elegant fashion. Cheers for the comments and tips guys :)


Sometimes you might need to find out where a module is being called from. For example if you have multiple different versions of a module and want to import the correct one, depending on what is calling that module. A quick Google turned up a really nice solution I have been using quite a bit recently.



For this example let's imagine we want to import MySQL-Python into a module we are writing, but we don't know if the person importing this module will be in Maya or Mobu. Consider the following package structure:

  • MyModule (this is where we want to import the SQL module)
    • MySQL
      • MySQL_26
      • MySQL_27
      • __init__.py

Regardless of the DCC we are writing for we effectively would like to be able to do something like: and let the import statement itself figure out the correct version of the module to import. Luckily there is a nice module called inspect, with a bunch of handy functions inside that we can take advantage of for this very reason. From within the base MySQL folder's __init__.py we can inspect the calling module: Looking at frm we will see we have a few different objects returned to us, that look something like this:
For our purposes we are interested in the frame object, and can retrieve the data we are after by using getmodule() on this object callingMod will now contain the module we made our import call from. In this example case it would look something like [mayaCore.myModule]
From the result its probably safe to say this call is coming from a module within Maya. We can then run our checks on the version of Maya calling this module and work out the correct module to import. So our MySQL folder's __init__.py will look something like this: Now when writing a module for any DCC we can simply:
It's worth pointing out that the above code will need to be adapted for your own pipeline. Although I only went over Maya, I find this a very convenient way of handling imports from multiple DCC's especially when different Python versions are involved.