[Python] Package, Module, and Function names

I am wondering what your thoughts are on naming Modules and Functions - specifically, is it ok for a module and a function to share the same name?

We encouter a situation very often where we have a single Function in a Module and the two share the same name.

We will then put that Module into a Package and import the function into the package’s namespace.


+ myPackage
| __init__.py
+- from .myScript import myScript
| myScript.py
+- def myScript():

this lets me do this:

from myPackage import myScript
myScript()

or:

import myPackage
myPackage.myScript()

However, this can cause some issues down the road, like if I add a second function to the module “myScript”, since the module’s namespace is overwritten by the function.

What standards or naming conventions do you use when creating collections of python scripts you wish to access from a common namespace?

Modules are primarily namespaces, that’s their most important job. Over the long haul you’ll be much happier if you think about them that way. Packages are mostly a hierarchy of modules, and thus of namespaces. The hierarchy of code is important information when you’re trying to figure out what’s going on: if you disguise it with imports and renames you may have a harder time understanding the code down the road. Thats why the Zen Of Python includes the line

Namespaces are one honking great idea – let’s do more of those!

Nesting is also (well, this is a personal thing for me) a more elegant way of hiding complexity. I much prefer:


import animation.rig.pose as pose
pose.set("zero", *cmds.ls(sl=True))
pose.delete("zero")
existing_poses = pose.list()

To a hypothetical alternative like


import animation.rig.pose.setRigPose as setRigPose
import animation.rig.pose.deleteRigPose as deleteRigPose
import animation.rig.pose.listRigPoses as listRigPoses

setRigPose("zero", *cmds.ls(sl=True))
deleteRigPose("zero")
existing_poses = listRigPoses()

Without the nesting you have to choose longer names anyway to avoid name clashes, so in most complex code it’s more or less a wash when it comes to typing - but the dotted version is somewhat easier to track back to the originating modules. Also, it’s a convenient place to store things besides functions. For example, animation.rig.pose might contain some constants that are handy:


ZERO = 'engineeringMadeMeCallThisSomethingStupidPose'
BIND = 'bindPose'
#... etc

which can ward off potential typos:


pose.set(pose.ZERO, *cmds.ls(sl=True))

… and which, naturally, can’t be done in a one module = one function system.

All that said, one module = one function is fine if the function is complex (and self contained) and you’d just like to keep it its own file. However any time a single function is big enough and complex enough to warrant a file to itself it’s probably in need of a refactor anyway: there is probably some good reusable code buried deep in there that could be brought out and made useful.

And yes: in the system you sketched out above you can’t access anything besides the eponymous function unless you do separate imports. Moreover it means you’ll see the same name in different contexts meaning different things, and will have to hop up to the imports at the top of your file to disambiguate. Not fun.

You might find this link has some useful tips.

Thanks for the insight, a couple of follow up questions.
If “pose” a single module file that contains related functions? or is “pose” a folder containing an init.py file?
I am summing that “animation” and “rig” and folders?

It would be a file, unless you made a folder named pose and threw in imports for submodules into it’s init.py file.

generally i find it is best to maintain name spaces, since this allows me to use similar naming conventions along everything I’m working on with out name clashing, and like what Theodox taking advantage of namespaces to group related things is always a good idea for simplification. Though most of this would be done via Classes in most cases.

Exactly - in a case like this ‘pose’ would ordinarily be a file with lots of functions, in the rig subpackage (= folder) of the animation package (= folder). I generally don’t use module level import/name replacement unless I want to transparently replace functional code while keeping the same public interface: For example, I might make a sourcecontrol package with ‘p4’ and ‘svn’ modules, but load the functions from one of them into the sourcecontrol package depending on an enviroment var, etc so code could run correctly without knowing that the source control commands were really p4 or svn commands.