PyMel warnings


#1

Hello,
When I run this type of code :

from pymel.core import*
lights = ls(lights=True)
for l in lights:
    delete(PyNode(l).getParent())

and I get this warnings :

// Warning: pymel.core.nodetypes : object ambientLightShape1 no longer exists //

With cmds or with generators I have no warning messages:

lights = cmds.ls(lights=True)
for l in lights:
    parent = cmds.listRelatives(l, p=True)
    delete(parent) 
lights = ls(lights=True)
[delete(PyNode(l).getParent()) for l in lights]

Generator returns list with None members.
I supose pumel is looking for PyNodes and can’t find them. I have tryed objExixts()command to checkit but without success.

Edit…
Just noticed this happens only on windows machines. On mac is ok.


#2

Do you have lights grouped under other lights? This will cause it:

from pymel import core as pm
pm.createNode('transform', n='group')
pm.createNode('transform', n='test1', p='group')
pm.createNode('transform', n='test2', p='group')
for node in pm.ls(['test1', 'test2']):
    pm.delete(node.getParent())

That’s because it finds test1 and deletes its parent (“group”). That causes test2 to be deleted, since it’s in the same group. pm.ls() already returned a list containing the test2 node before we deleted it, so we call getParent() on it when it no longer exists, which raises a warning and returns None.

That doesn’t happen with “cmds”, since it’s just returning a list of strings, and cmds.listRelatives([‘unknown’], p=True) just returns an empty list.

FYI, you don’t need to instantiate PyNode yourself, pm.ls() will return PyNodes for you.


#3

Thanks for your reply. Did’nt know that ls() already returns objects.
OK. I figured out why it happens. In the code I have another line below this loop and it uses light variable to loop through.
How do I convert list with Pymel objects to regular string list? It loops through the list members that does not exists. At the same time list is not empty. With cmds it’s ok.


#4

I’d suggest first to collect the objects to remove in a list and then remove them in a seperate step:


lights = pm.ls(type="light")
lightTransforms = [l.getParent() for l in lights]
pm.delete(lightTransforms)

#5

Does not work.


#6

Hmm… intersting. Which maya versio do you use?
Just tried your very first code and it completes without warnings in Maya2015.

from pymel.core import*
lights = ls(lights=True)
for l in lights:
    delete(PyNode(l).getParent())

#7

The problem is when you loop through the list one more time

lights = ls(lights=True)
for l in lights:
    delete(l.getParent())
    
for l in lights:
    print l

With cmds module doese not get warnings,

lights = cmds.ls(lights=True)
for l in lights:
    p = cmds.listRelatives(l, p=True)
    cmds.delete(p)

for l in lights:
    print l

#8

Found solution but don’t think it’s right way :))

lights = ls(lights=True)
lightString = str(lights).split()

for l in lights:
    delete(l.getParent())
    
for l in lightString:
    print l

#9

If you simply need the name of the light, then this is a valid way. A more pythonic way would be:

lights = pm.ls(type = "light")
lightNames = [l.name() for l in lights]

The only problem was that you accessed a pymel object which then tried to access the light shape which did not exist any more. That’s all. So collecting all info before deleting it solves all problems.


#10

That works fine! Thanks!