PyMel - name at creation inconsistency

228 views
Skip to first unread message

johan Borgström

unread,
Mar 5, 2015, 11:42:49 AM3/5/15
to python_in...@googlegroups.com
I am using PyMel to create some locators in a scene. I give the locator a name at creation and parent the locator to a group. The second iteration of the script I get a MayaNodeError (Maya Node does not exist (or is not unique)).

This behaviour seems a little bit weird to me. If I do the same but instead create a polyCube it works as expected. I could use various workarounds, for instance parent and then rename, which works fine...

This is some sample code to reproduce the error:
# polyCube, works fine
for x in range(10):
    grp = pm.group(em=True)
    t = pm.polySphere(n='test', ch=False)[0]
    pm.parent(t, grp)
    

# Error: MayaNodeError: Maya Node does not exist (or is not unique):: u'test'
for x in range(10):
    grp = pm.group(em=True)
    t = pm.spaceLocator(n='test')
    pm.parent(t, grp)
    

# workaround
for x in range(10):
    grp = pm.group(em=True)
    t = pm.spaceLocator()
    pm.parent(t, grp)
    t.rename('test')


Does anyone have an idea why this does not work?

Best Regards,
Johan

Mahmoodreza Aarabi

unread,
Mar 5, 2015, 12:25:08 PM3/5/15
to python_in...@googlegroups.com

i show my code, and you can find differentiation.

i think you should not set name when you create object(locator)

import pymel.core as pm
for x in range(10):
    grp = pm.group(em=True)
    t = pm.polySphere(n='test', ch=False)[0
]
    t.setParent(grp)


for x in range(10):
    grp = pm.group(em=True
)
    loc = pm.spaceLocator()
    loc.rename('test')

Good luck.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/777f2425-3929-4364-a42e-594e1bb9bf94%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--


Bests,
madoodia

johan Borgström

unread,
Mar 5, 2015, 12:31:30 PM3/5/15
to python_in...@googlegroups.com
Thanks,

I had that solution listed as a "workaround" in my code as well. I am interested to know why it works on some nodes but not on the locator.

Br,
Johan

Marcus Ottosson

unread,
Mar 5, 2015, 12:37:31 PM3/5/15
to python_in...@googlegroups.com

I had a good look at this, and it looks to be quite the interesting quirk. :)

Here’s the same problem in maya.cmds.

from maya import cmds

for x in range(2):
    grp = cmds.group(em=True)
    t = cmds.polySphere(n='test')[0]
    assert isinstance(grp, unicode)
    assert isinstance(t, unicode)
    cmds.parent(t, grp)

Merely replacing polySphere with spaceLocator causes the error for me in Maya 2015, and I have no idea why.

Good find!

johan Borgström

unread,
Mar 5, 2015, 1:38:25 PM3/5/15
to python_in...@googlegroups.com
Thanks for testing with maya.cmds as well marcus :)

I guess we have to go with the renaming workaround, but it would be interesting to find out why this is!

// Johan

Chris Lesage

unread,
Mar 5, 2015, 1:52:21 PM3/5/15
to python_in...@googlegroups.com
It's because when there are more than one nodes that have the same non-unique name, Maya sees them as this:

|group1|test
|group2|test
|group3|test

So it can't find "test" anymore. Even though you are casting it as a variable, there is some bug. This bug only seems to occur for locators.

Is there a reason you aren't using unique names?

If you do need non-unique names, then this works: Rename the locator after creation.

for x in range(10):
grp = pm.group(em=True)
t = pm.spaceLocator()
pm.rename(t, 'test')
pm.parent(t, grp)


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Chris Lesage

unread,
Mar 5, 2015, 1:52:59 PM3/5/15
to python_in...@googlegroups.com
Oh sorry, that was your workaround. :)

Marcus Ottosson

unread,
Mar 5, 2015, 2:09:01 PM3/5/15
to python_in...@googlegroups.com

Well, as a quirk, it’s interesting (and odd), but as for a solution, I’d mirror what Chris is saying about simply using unique names, and not rely on the (apparently obscure) auto-naming feature of Maya for anything going into production.

Something like this should do it.

for x in range(10):
    grp = pm.group(em=True
)
    t = pm.spaceLocator(n='test_%s' % x)
    pm.parent(t, grp)

But surely (hopefully) you’ve got better intentions that to use test and an arbitrary number as object name. But that’s just me. :)

Geordie Martinez

unread,
Mar 5, 2015, 2:13:08 PM3/5/15
to python_inside_maya
Another approach is to at the "#" into your naming schema. this will increment to the next unique number for that name.
then the name will not have a collision with other objects in your scene

for x in range(10):
    grp = pm.group(em=True)
    t = pm.spaceLocator(n='test#')  # add the pound symbol to get next unique number.
    pm.parent(t, grp)


johan Borgström

unread,
Mar 5, 2015, 2:17:45 PM3/5/15
to python_in...@googlegroups.com
Thanks Chris,

One of the reasons that I like to use PyMel is that when you create an object you get a reference to that object and you are not dependent of the name when you want to find the object. 

When I was doing MEL scripting I ran into this issue many times. As you now we can have multiple objects with the same name as long as they have unique dag paths. So if we have one object called test parented under grp1 ( '|grp1|test' ) and one object called test at the root level ( '|test' ) I could use '|test' to find the one at root level. This is also true if you use maya.cmds.

But since I am using PyMel in this case I got a bit surprised by this.

Yup, it seems like I will use the rename trick :)

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Marcus Ottosson

unread,
Mar 5, 2015, 2:18:40 PM3/5/15
to python_in...@googlegroups.com
Wuw, nice one Geordie! 

You would think that this is what Maya was doing on it's own.

johan Borgström

unread,
Mar 5, 2015, 2:22:52 PM3/5/15
to python_in...@googlegroups.com
Thanks Geordie!

I did not know that, I agree with Marcus really nice one :)
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Chris Lesage

unread,
Mar 5, 2015, 2:55:44 PM3/5/15
to python_in...@googlegroups.com
"One of the reasons that I like to use PyMel is that when you create an object you get a reference to that object and you are not dependent of the name when you want to find the object."

Yes, I agree. Well, in this case, you are dependent on the name. Or you cause a bug. :)

Also I couldn't resist writing this as list comprehensions. Doing it this way stores your locators as a list of objects that you can reference even after your range(10) is complete.

locators = [pm.spaceLocator(n='test#') for x in range(10)]
groups = [pm.group(loc, n='group#') for loc in locators]

By the way, zfill() is a nice way to give number padding when making a numbered naming convention. This would make test_000, test_001, test_002, etc. ...But this will still cause a nodeError if you don't have unique names:

locators = [pm.spaceLocator(n='test_{0}'.format(str(x).zfill(3))) for x in range(10)]
groups = [pm.group(loc, n='group#') for loc in locators]



To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/7d8478c4-33e5-4e5b-a93d-013c0a245bcc%40googlegroups.com.

Eric Thivierge

unread,
Mar 5, 2015, 3:00:23 PM3/5/15
to python_in...@googlegroups.com
One thing to maybe mention Chris, is that while list comprehensions take up less lines, the quick readability may diminish. If you have lots of them lined up next to each other or used consecutively it can be very hard to read the code. Especially if it isn't your own.

It's a balance of use and readability.

Eric T.

Roy Nieterau

unread,
Mar 5, 2015, 4:33:10 PM3/5/15
to python_in...@googlegroups.com, ethiv...@hybride.com
I vaguely remember submitting this as a bug and getting a 'Yes, we know' from Autodesk.
Anyway, giving the name right away only messes with the spaceLocator command.
I remember spotting it in one other command, but I can't remember which one it was.

Since Maya selects the newly created item you can actually query the selection as a workaround! :)

import maya.cmds

def safeSpaceLocator(*args, **kwargs):
   
""" Wrapper around spaceLocator command since it doesn't return unique names correctly if name argument is provided """
    maya
.cmds.spaceLocator(*args, **kwargs)
   
return maya.cmds.ls(sl=1)

The same fix works for PyMel of course.
If you'd rather stay away from querying selections because you might feel it's the root of all evil.
Then here's another workaround, create the node with the createNode command.
print maya.cmds.createNode('locator', name='test')

If you want to have a fixed command without querying selection that still allows you to manipulate it with argument like the default spaceLocator command, then here's a draft:
import maya.cmds

def safeSpaceLocator(*args, **kwargs):
   
    createKwargs
= {}
    name
= kwargs.pop('name', kwargs.pop('n', None))
   
if name is not None:
        createKwargs
['name'] = name
       
    locator
= maya.cmds.createNode('locator', **createKwargs)
   
   
if args or kwargs:
        maya
.cmds.spaceLocator(locator, e=1, *args, **kwargs)
   
   
return [locator]

Note that it doesn't allow to use the last safeSpaceLocator() command in edit mode.
It's trivial to implement if someone wants to monkey patch Maya's command plus has the urge to work around querying the selection.

/geek out
-Roy

johan Borgström

unread,
Mar 6, 2015, 10:36:26 AM3/6/15
to python_in...@googlegroups.com, ethiv...@hybride.com
Thanks Roy,

Very interesting to hear. I also tried the createNode function as a workaround, and it works fine as you pointed out, but I wanted to understand why using the spaceLocator command with the name param would give me an error. So it seems like this is a bug. Case closed :)

In the same script I also got an error using the ikHandle command. Seems to be a similar issue. Without Geordies pound sign trick, the following code also gives an error.

for x in range(2):
    
    jnt_list = [pm.joint(p=p) for p in [(0,0,0), (5,5,0), (10,0,0)]]
    ik_handle, eff = pm.ikHandle(sj=jnt_list[0], ee=jnt_list[-1], name='test_ik#')
        
    grp = pm.group(em=True)    
    pm.parent(jnt_list[0], ik_handle, grp)
    pm.select(deselect=True)
    
Reply all
Reply to author
Forward
0 new messages