Script not working after reboot

Hello all, I’ve reccently wrote a script, my first script in maya using python, I’m still very new to scripting in general as you can probably tell from my script.

The script was designed to help me create some simple 3d modules for a project Im working on. And it works great does everything I need it to, that is until I close maya and reopen it.

All of a sudden none of my expressions work and I get the error message:

# Error: NameError: name 'molecule1' is not defined # 
// Error: An execution error occured in the expression molecule1_exp. //

molecule1 is what I named the instance when I created it from the Atom Class. It seems that when I reboot maya it seems to loose the instance, I’m not really sure whats going on, but I cant access any of the functions inside the class.

Here is my script:


class Atom(object):
	def __init__(self):
		import maya.mel as mel
		
		#Create Particles
		csel = mc.ls(selection=True) 
		cv = mc.getAttr(csel[0]+ ".cv[li]")
[/li]		self.name = csel[0]
		mc.hide(csel)
		mc.nParticle(p=cv,name=self.name + "_nP")
		self.pcount = mc.particle(self.name + "_nP", query=True, ct=True)	
	
		# Locator Creation
		for pt in range(0,self.pcount):
			pctp = mc.nParticle(self.name + "_nP", q=True, at="position", id = pt)
			pctpx = pctp[0]
			pctpy = pctp[1]
			pctpz = pctp[2]
			mc.spaceLocator(name=self.name + "_Locator_" + str(pt))
			mc.setAttr (self.name + "_Locator_" + str(pt) + ".translate", pctpx,pctpy,pctpz)	
		
		#Define cylinder bonds function
		for x in range(0,self.pcount):
			mc.polyCylinder(name=self.name + "_Bond_" + str(x), ax=(0,0,1), sx=10, radius = mc.getAttr(self.name + "_nPShape.radius")/4)
			mc.cluster(self.name + "_Bond_" + str(x) + ".vtx[0:9]", n=self.name + "_BondClusterTop_" + str(x),rel=True)
			mc.cluster(self.name + "_Bond_" + str(x) + ".vtx[10:19]", n =self.name + "_BondClusterBottom_" + str(x),rel=True)
	
		#Parent clusters to locators
		#First set of bonds
		if self.pcount%2 ==0:
			for x in range(0,self.pcount,2):
				mc.aimConstraint(self.name + "_BondClusterTop_" + str(x) + "Handle", self.name + "_BondClusterBottom_" + str(x) + "Handle", mo=True)
				mc.aimConstraint(self.name + "_BondClusterBottom_" + str(x) + "Handle",self.name + "_BondClusterTop_" + str(x) + "Handle", mo=True)
				mc.pointConstraint(self.name + "_Locator_" + str(x), self.name + "_BondClusterTop_" + str(x) + "Handle")
				mc.pointConstraint(self.name + "_Locator_" + str(x+1),self.name + "_BondClusterBottom_" + str(x) + "Handle")
		else:
			for x in range(0,self.pcount-1,2):
				mc.aimConstraint(self.name + "_BondClusterTop_" + str(x) + "Handle",self.name + "_BondClusterBottom_" + str(x) + "Handle", mo=True)
				mc.aimConstraint(self.name + "_BondClusterBottom_" + str(x) + "Handle",self.name + "_BondClusterTop_" + str(x) + "Handle", mo=True)
				mc.pointConstraint(self.name + "_Locator_" + str(x),self.name + "_BondClusterTop_" + str(x) + "Handle")
				mc.pointConstraint(self.name + "_Locator_" + str(x+1),self.name + "_BondClusterBottom_" + str(x) + "Handle")
	

		#Second set of bonds
		for x in range(1,self.pcount-1,2):
			mc.aimConstraint(self.name + "_BondClusterTop_" + str(x) + "Handle",self.name + "_BondClusterBottom_" + str(x) + "Handle", mo=True)
			mc.aimConstraint(self.name + "_BondClusterBottom_" + str(x) + "Handle",self.name + "_BondClusterTop_" + str(x) + "Handle", mo=True)
			mc.pointConstraint(self.name + "_Locator_" + str(x),self.name + "_BondClusterTop_" + str(x) + "Handle")
			mc.pointConstraint(self.name + "_Locator_" + str(x+1),self.name + "_BondClusterBottom_" + str(x) + "Handle")	

		#Joining the ends	
		mc.aimConstraint(self.name + "_BondClusterTop_" + str(self.pcount-1) + "Handle",self.name + "_BondClusterBottom_" + str(self.pcount-1) + "Handle", mo=True)
		mc.aimConstraint(self.name + "_BondClusterBottom_" + str(self.pcount-1) + "Handle",self.name + "_BondClusterTop_" + str(self.pcount-1) + "Handle", mo=True)
		mc.pointConstraint(self.name + "_Locator_" + str(self.pcount-1),self.name + "_BondClusterTop_" + str(self.pcount-1) + "Handle")
		mc.pointConstraint(self.name + "_Locator_0",self.name + "_BondClusterBottom_" + str(self.pcount-1) + "Handle")

		#Create Springs
		mc.spring(self.name + "_nP", minMax=True, urp=True,mxd=100, name=self.name + "_BondSpring")

		#Create Groups
		mc.group(self.name + "_nP", name=self.name + "_Group")
		mc.group(self.name + "_Bond*",name=self.name + "_Bonds_Group", parent=self.name + "_Group")
		mc.group(self.name + "_Locator*",name=self.name + "_Locators_Group",parent=self.name + "_Group")
		mc.parent(self.name, self.name + "_Bonds_Group")

		self.expSt ="python(\""  + self.name + ".nploc()\");"
		mc.expression(n=self.name + "_exp",s=self.expSt, ae=True)
		eval("self.name + \".nploc()\"")

	#Expression Deffinition
	def nploc(self):
		for x in range(0,self.pcount):
			ptp = mc.nParticle(self.name + "_nP", q=True, at="position", id = x)
			ptpx = ptp[0]
			ptpy = ptp[1]
			ptpz = ptp[2]
			mc.setAttr(self.name + "_Locator_" + str(x) + ".translate",ptpx,ptpy,ptpz)

Its rather annoying as took me a couple of days of work to make the script, with it being my first one and all I was rather proud up until this point.

Can anyone help me out?

Many Thanks.

Tom

If I’m understanding you correctly. You created an instance of the class, and the rebooted maya and it’s gone. That should be how it works. The instance is contained within that particular instance of maya, so when maya closes, the class instance is removed. If you want to maintain that class instance between several instances of maya you’ll need to do something like Pickle the instance to a file.

Thank you for the reply, the only reason I created it as a class and instance system was to allow me to run the script multiple times on different objects.

I have use pickle to store databases and strings before but never a class instance, how exactly would I go about this?

Or is there a better way to get the script to run on several objects within the scene, the issue was happening with the names of variables being the same for each object, so I used a class and a separate instance for each object to separate the variables.

Thanks.

I’m not really sure what the issue is then. If you’re just running this on several objects, you shouldn’t have an issue, just call each Instance of the class something different, or even after the work is done, you can just stomp over the original instance. Python has its own garbage collector. Or you can have it accept any number of objects and loop through them.

Also, if you’re passing the name of the object into the class, grab the objects FullPathName. If you get that, it will always be unique. Maya doesn’t allow for objects to have the same FullPathName. Commands like cmds.ls(sl=True, long=True) will get the long name of the selected object.

pickling stuff is here pickle — Python object serialization — Python 3.12.6 documentation

Thanks for the tip about full path names.

I do name each instance something different, but the issue is with using this method, unless I pickle it or find a different way, as soon as I reboot maya then my expression will no longer work as it uses the instances.

This way I have mol1.pcount and mol2.pcount which are used to count the number of particles. The problem is the expression access a function defined within the class, so each instance has a .nploc() function. But as you stated when I reload maya it clears the instances.

I think a better way would be to edit the expression, so instead of using a function inside each instance, I might be able to create a list of all the nParticle objects in my scene, and then iterate through the list and through the number of particles for each item in the list and try and do it that way.

EDIT: Ok I changed the expression so that instead of it running a function from each instance it runs one global function that iterates through the list of nparticle objects and through each particle of those objects. This means all I have to do when I open the file again is rerun the script to define the new function. Plus it means I only need one global expression now rather than one for each instance.

New expression:

def nploc():
	partList = mc.ls(et="nParticle")
	for np in partList:
		pcount = mc.particle(np, query=True, ct=True)
		for x in range(0,pcount):
			ptp = mc.nParticle(np, q=True, at="position", id = x)
			ptpx = ptp[0]
			ptpy = ptp[1]
			ptpz = ptp[2]
			mc.setAttr(np[:-8] + "_Locator_" + str(x) + ".translate",ptpx,ptpy,ptpz)

Thanks you for your help.