Selecting Namespace Objects in[Maya] via[ Python]

I’m having trouble selecting namespace Maya objects via Python.

In my scene, I have 2 items named obj:pShere1 and pSphere1. I want to select them both with a wildcard.

When I execute select(’*pSphere1’, r=True), only pShere1 is selected. The namespace object, obj:pShere1 is not.

I’m sure I’m missing something obvious here. Any suggestions?

you need the “recursive” flag from the “ls” command to search through namespaces.

you could also try:

select('*:pSphere1', r=True)
1 Like

This might muddy the waters a bit ( feel free to skip if rgkovach’s answer is doing the job ) but namespaces are a ridiculous quagmire in Maya. For example:


// for a namespace named 'fred' //

ls "pCube1"
// Result: pCube1 // 

ls "*:pCube1";
// Result: fred:pCube1 // 

ls -r 1 "pCube1"
// Result: pCube1 fred:pCube1 // 

Note that the “*:” form excludes results from the root namespace, which stinks.

There’s also this charming bit of lame-ass engineering - there’s a special relative lookup mode which can change the meaning and behavior of all sorts of other commands (from the docs on the namespace command):

List all mesh objects in the scene:
ls -type “mesh”;

The above command lists all mesh objects in the root and any child namespaces. In relative name lookup mode, all names will be displayed relative to the current namespace. When not in relative name lookup mode (the default behaviour in Maya), results are printed relative to the root namespace.

Using a “" wildcard:
namespace -set myNS;
ls -type "mesh "
”;

In relative name lookup mode, the “" will match to the current namespace and thus the ls command will list only those meshes defined within the current namespace (i.e. myNs). If relative name lookup is off (the default behaviour in Maya), names are root-relative and thus "” matches the root namespace, with the net result being that only thoses meshes defined in the root namespace will be listed.

You can force the root namespace to be listed when in relative name lookup mode by specifying “:" as your search pattern (i.e. ls -type mesh ":” which lists those meshes defined in the root namespace only). Note that you can also use “:*” when relative name lookup mode is off to match the root if you want a consistent way to list the root.

Listing child namespace contents:
ls -type mesh “:”;

For an example to list all meshes in immediate child namespaces, use “:”. In relative name lookup mode “:” lists those meshes in immediate child namespaces of the current namespaces. When not in relative name lookup mode, “:” lists meshes in namespaces one level below the root.

Recursive listing of namespace contents:
Example: ls -type mesh -recurse on “*”

The -recurse flag is provided on the “ls” command to recursively traverse any child namespaces. In relative name lookup mode, the above example command will list all meshes in the current and any child namespaces of current. When not in relative name lookup mode, the above example command works from the root downwards and is thus equivalent to “ls -type mesh”.

That last bit also means that the results of ls -r 1 will vary based on the active namespace set as well. To be absolutely safe you have to switch to the root namespace or you can miss someting in a sibling
Short story: namespaces are a weak-ass implementation of a feature that should be critical path. Use with care, and always try to be aware of what namespace you are in before doing open-ended queries

Big thanks to rgkovach123 and Theodox. Your comments are helpful!

I found something very interesting that seems to help with my particular situation.

Using the .stripNamespace() method attached to nt.Joint object, I’m able to get around my issue of having mixed namespace and non-namespace items I need to wildcard. I’m doing something like this:

selected = ls(sl=True)
if selected[0].stripNamespace() == 'Reference':
    print('detected Reference')

Cool thing is that it doesn’t seem to care whether the item has namespace or not. Returns the same result either way.

or you could use a lambda to strip the results of a command

no_ns = lambda path : path.rpartition(":")[-1]

However it’s always dangerous to mix commands on namespaced and un-namespaced objects – you can’t be sure which one you’re working on just by looking at the code, since the namespace context could be set elsewhere. If you know you’re dealing with namespaces, it’s always safest to use absolute namespace references for everything except display.