The Python framework structure simply refers to the hierarchical organization of your code, tools and resources. Build a logical structure which results in discover-ability, flexibility, and readable code. We will build one up from scratch. While not necessary, if you do not have an IDE set up, check this post out on how to set one up for yourself and speed up the creation of Python modules and packages and increase efficiency when coding.
Python framework base structure
First, give your framework a root folder name (I will use LCG). This is the folder that can be consumed by end users of your tools. At the next level, create your python root. This is the folder that we add to the sys.path to import our modules. At this level, also create any “site folders” you need. I create a Maya and a Houdini folder for this purpose. For some tips on how to modify the Maya environment for your framework and the specifics of the Maya site folder, check this post.
The Python structure
In the Python root, create a top level package that will house our Python framework. It is a good idea to create a layer of separation at this level. I named my package lcg. Now our Python imports will all begin with import lcg making it clear where the code is coming from.
In the root of the lcg package, I highly recommend creating a package that will house 3rd party modules and packages that our framework will use. Name it “lib”. The path to the lib folder will also be added to sys.path because a lot of times, 3rd party packages will assume internal imports from the root.
Next, create a package for each digital content creation (dcc) that you will be writing tools for. This is what I have so far. Finally just creates packages in a logical manner, grouping things functionally. If you create mesh as a package, you can still create the functions at the mesh namespace level by adding them into the __init__.py module. Example below. Design how you want to call your code.
Here is how you dynamically modify the Python environment to handle importing separate packages with identical names. Back in the day, this was necessary for 32 and 64 bit versions of certain Python libraries. The cases I run into these days involve certain Python libraries requiring to run with a Python version that has been compiled with the same version of Visual Studio.
Below we resolve the Python environment for the Perforce module import between Python 2.7 and 2.6. The first thing that happens when you import a package, is that the __init__.py gets evaluated. The sys module’s executable and winver functions allows you to query information about the Python executable that is importing the module. We can then add the correct path to the module that is being imported.
print('Perforce imported from application %s using the %s interpreter' % (sys.executable, sys.version))
__bitDepth = 'win64'
__pythonVersion = sys.winver.replace('.', '')
__thisDirectory = os.path.dirname(__file__).replace('\\', '/')
__pydPath = '%s/p4_%s' % (__thisDirectory, __pythonVersion)
Hopefully, these little tips and tricks when it comes to designing your own tool framework helps.
Please drop a comment below if this is helpful to you.